Можно ли эффективно вставить слова в этих строках bash в таблицу sqlite?

still logged as user, ssh-copy-id root@vm1 (skipping the password auth step...) succeeds, copying the [user]'s public key to the authorized_keys file in vm1's root ~/.ssh/ folder. The key is still tagged with the name and machine of the [user].

Принцип аутентификации на основе ключа SSH -заключается в том, что:если клиент может криптографически доказать, что он владеет закрытым ключом, который соответствует открытому ключу в ~/.ssh/authorized_keysфайле запрошенного имени пользователя на сервере, доступ разрешен. Вот именно. «Имя и машина [пользователя]» на самом деле представляют собой текстовое поле свободной -формы, которое позволяет людям легко идентифицировать конкретный открытый ключ. Содержимое этого поля никак не используется при аутентификации.

По умолчанию сервер SSH не заботится о том, какое имя пользователя входящее соединение утверждает на стороне клиента, потому что:

  • клиент может не захотеть сообщать об этом серверу
  • сервер никак не может проверить имя пользователя на стороне клиента -
  • Даже если это так, злонамеренный клиент с украденным ключом может быть настроен с любым именем пользователя на стороне клиента -, которое выгодно клиенту.

Если вы хотите ограничить использование аутентификации с помощью ключа SSH, вы можете сделать это, поставив перед ключом SSH в файле authorized_keysпрефикс from="<hostname-or-IP-address-pattern>". Как сказано на справочной странице sshd:

The purpose of this option is to optionally increase security: public key authentication by itself does not trust the network or name servers or anything (but the key); however, if somebody somehow steals the key, the key permits an intruder to log in from anywhere in the world. This additional option makes using a stolen key more difficult (name servers and/or routers would have to be compromised in addition to just the key).


To me, this seems to weaken the root access protection on the target machine because the user's public key verifies the login privilege, but the target root's corresponding private key is not stored in a restricted root account ~/.ssh/ folder on the source machine.

Это верно только в том случае, если исходная машина всегда гарантированно находится под тем же административным контролем, что и целевая машина. SSH не предполагает этого и признает, что бесполезно основывать что-либо на том, кем пользователь исходной машины называет себя , если нет способа проверить это утверждение.


Если вы имели в виду, что user@vm1запустил ssh-copy-id root@vm1и успешно ввел пароль root, то вы, возможно, были удивлены тем, что ssh-copy-idсделал в этом случае. Если в user@vm1:.ssh/id_*не было закрытого ключа SSH, а sshdиз vm1разрешала пересылку агента SSH, тогда ssh-copy-idиспользовал соединение агента для получения открытого ключа с клиентского хоста Mac. И вот как открытый ключ, помеченный именем и машиной [user], оказывается в файле root@vm1:.ssh/authorized_keys.

Современная macOS имеет расширенный ssh-agent, который интегрируется со связкой ключей macOS и по умолчанию доступен для каждого сеанса пользователя macOS. Если вы ожидаете простое старое поведение OpenSSH, это также может быть сюрпризом.

0
05.05.2021, 20:42
3 ответа

Линейный инструмент sqlite3команда -не поддерживает подготовленные операторы , поэтому любая попытка сделать это в сценарии оболочки приведет к проблемам с un -экранированными кавычками и подобно. Работа с переменными в кавычках и без кавычек уже вызывает некоторую головную боль в shell/bash, и эта боль только усугубляется, когда вы работаете с базой данных SQL, которая имеет свои собственные требования к заключению в кавычки.

Подобные задачи следует выполнять на языке с библиотекой SQLite. Наиболее часто используемые языки, как компилируемые, так и интерпретируемые, имеют такие библиотеки.

Вот несколько примеров того, как это сделать в Perl:

Все эти примеры требуют установки библиотечных модулей DBI и DBD ::SQLite . Если вы используете какой-либо дистрибутив Linux, они почти наверняка будут доступны в виде пакетов. Например, в Debian запустите sudo apt install libdbd-sqlite3-perl, чтобы установить их оба. Большинство других языков будут иметь аналогичные библиотеки.

Кстати, еще одна причина отказа от использования sh или bash (или других оболочек )заключается в том, чтобы избежать боли, связанной с кавычками и разделением слов -и связанными с ними проблемами, которые существуют в сценариях оболочки, но не в других языках. (у них есть свои проблемы и причуды ).

С двумя массивами, @firstи@last:

#!/usr/bin/perl

use strict;
use DBI;

my $dbfile= './people.db';
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile");

my @first = qw(John Paul George Ringo);
my @last = qw(Lennon McCartney Harrison Starr);

$dbh->do('CREATE TABLE IF NOT EXISTS people(fname TEXT, lname TEXT)');

my $sth = $dbh->prepare('INSERT INTO people (fname, lname) VALUES (?,?)');

for my $i (0..$#first) {
  $sth->execute($first[$i],$last[$i]);
};

Здесь важно то, что, поскольку я использовал подготовленный оператор, мне не нужно заботиться о каких-либо раздражающих символах, таких как кавычки, в любом из имен, и мне не нужно предпринимать никаких специальных действий для обработки с ними. Подготовленный оператор заставляет все это обрабатываться автоматически.

Сохраните это как, например, sql-arrays.plи сделайте его исполняемым с помощью chmod +x sql-arrays.pl.

Вы можете проверить правильность вставки записей из оболочки:

$ sqlite3 people.db -cmd ".mode column" "SELECT * FROM people;"
fname   lname    
------  ---------
John    Lennon   
Paul    McCartney
George  Harrison 
Ringo   Starr    

Конечно, вы можете написать Perl-скрипт для запуска оператора SELECT и вывода записей в любом удобном для вас формате. Я оставлю это в качестве упражнения для читателя.

С ассоциативным массивом (или хешем ),%people:

#!/usr/bin/perl

use strict;
use DBI;

my $dbfile= './people.db';
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile");

my %people = (
  'John'   => 'Lennon',
  'Paul'   => 'McCartney',
  'George' => 'Harrison',
  'Ringo'  => 'Starr',
);

$dbh->do("CREATE TABLE IF NOT EXISTS people(fname TEXT, lname TEXT);");

my $sth = $dbh->prepare('INSERT INTO people (fname, lname) VALUES (?,?)');

for my $person (keys %people) {
  $sth->execute($person,$people{$person});
};

ПРИМЕЧАНИЕ Хеши :хранятся в произвольном порядке, поэтому записи будут вставлены в базу данных в полу-случайном порядке. Вы можете использовать sort keys %peopleвместо keys %people, но это будет вставлять записи в отсортированном порядке (Джордж, Джон, Пол, Ринго ), который не совпадает с порядком, указанным (Джон, Пол.,Джордж,Ринго ).

В большинстве случаев при работе с хэшами порядок не важен. Когда это так, обычно используют отдельный индексированный массив для хранения требуемого порядка и перебирают его вместо полу--случайных хеш-ключей.

напр. @order=qw(John Paul George Ringo);и позже for my $person (@order) {... };вместо for my $person (keys %people) {... }.

Во всяком случае, вы можете видеть, что порядок записей в БД отличается от первой версии:

$ rm -f people.db
$./sql-hash.pl
$ sqlite3 people.db -cmd ".mode column" "SELECT * FROM people;"
fname   lname    
------  ---------
John    Lennon   
Ringo   Starr    
George  Harrison 
Paul    McCartney

Стоит также отметить, что это довольно надуманный пример, -хеш-ключ должен быть уникальным , а имена далеко не таковы. Несмотря на то, что этот пример хорошо демонстрирует основную идею выборочных данных, в реальном мире хеш-ключ будет представлять собой UUID, неповторяющуюся последовательность -или какой-либо другой уникальный идентификатор, а соответствующее поле в базе данных будет быть ПЕРВИЧНЫМ КЛЮЧОМ.

Что еще более важно, при выполнении запроса SELECT модуль DBI может возвращать совпадающие строки в виде хэша или ссылки на хэш, и вы можете перебирать ключи для вывода и/или обработки данных.

Кстати, bashтакже имеет ассоциативные массивы, а также индексированные массивы. Как и ksh, zsh и awk. Большинство других языков имеют ту или иную форму ассоциативного массива или кортежей или подобных.

С массивом строк, содержащих полные имена,@people:

#!/usr/bin/perl

use strict;
use DBI;

my $dbfile= './people.db';
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile");

my @people = ('John Lennon', 'Paul McCartney', 'George Harrison', 'Ringo Starr');

$dbh->do("CREATE TABLE IF NOT EXISTS people(fname TEXT, lname TEXT);");

my $sth = $dbh->prepare('INSERT INTO people (fname, lname) VALUES (?,?)');

foreach (@people) {
  my ($first,$last) = split;
  $sth->execute($first,$last);
};

В этой версии каждое полное имя разбивается на имя и фамилию, а затем вставляется в базу данных.

Эта форма особенно полезна, если вы хотите прочитать список имен из текстового файла (по одному имени в строке )вместо использования жесткого -закодированного массива строк.

Ни один из приведенных выше сценариев не может работать с людьми, у которых есть отчества или титулы, такие как мистер или доктор, или с теми, чьи правила именования не такие, как в большинстве англоязычных -стран мира. Приложив достаточные усилия, вы можете заставить их изменить свои имена в соответствии с вашей программой, но, вероятно, проще просто изменить алгоритм (и структуру базы данных ), чтобы справляться с такими реальными -мировыми неприятностями. Люди могут быть такими неудобными. Особенно звезды эстрады.

3
28.07.2021, 11:34

Вот bashскрипт, который сделает <MAGIC>то, что вы хотите

#!/bin/bash
#
FNAMES="John Paul George Ringo Andrew Nicci"
LNAMES="Lennon McCartney Harrison Starr O'Brien Müller"

# Convert strings to space-separated arrays (lists)
# Bad things will happen if you have names with spaces (e.g. "Sarah" + "Maddison Smith")
fnames=($FNAMES)
lnames=($LNAMES)

# Create table
# echo "sqlite3 people.db 'CREATE TABLE people(fname TEXT, lname TEXT);'"
sqlite3 people.db 'CREATE TABLE people(fname TEXT, lname TEXT);'

# Loop across data
# Hope that there are the same number of surnames as forenames
for ((i=0; i<${#fnames[@]}; i++))
do
    # Escape quotes (' becomes ''). Other SQL variants may require a different process
    fname="${fnames[i]//\'/\'\'}"
    lname="${lnames[i]//\'/\'\'}"
    
    # Insert the data
    # echo "sqlite3 people.db \"INSERT INTO people(fname, lname) values ('$fname', '$lname');\""
    sqlite3 people.db "INSERT INTO people(fname, lname) values ('$fname', '$lname');"
done

# Report on the result
# echo "sqlite3 people.db -cmd '.mode column' 'SELECT * FROM people;'"
sqlite3 people.db -cmd '.mode column' 'SELECT * FROM people;'

Я проверил -с двумя дополнительными именами в наборе данных на предмет потенциальных проблем с границами -, и все работает, как и ожидалось:

John        Lennon
Paul        McCartney
George      Harrison
Ringo       Starr
Andrew      O'Brien
Nicci       Müller
2
28.07.2021, 11:34

Я написал bash-функцию под названием MAGIC, которая берет n списков, разделенных пробелами, и преобразует их в набор значений SQL, таким образом сохраняя большую часть исходного синтаксиса. он использует стандартное экранирование SQL, которое, насколько я могу судить, является синтаксисом, ожидаемым Sqlite.

Это будет работать для любого количества столбцов больше нуля.

# MAGIC  a variadic function. 
# named for a comment in the question.
# takes one or more space-delimited lists and turns them
# into an SQL VALUES clause with SQL99 standard quoting.
# returns true, presents the result on stdout.
MAGIC(){
   local sep1 sep2 argz i
   argz=( "$@" )
   argz[0]="${argz[0]} " # ensure termination
   sep1="VALUES " 
   while [ "${argz[0]}" != "" ]
   do
      sep2=""
      echo -n "$sep1("
      for(( i=0; i<$# ; ++i ))
      do
         v=${argz[$i]%% *}
         echo -n "$sep2'${v//\'/\'\'}'"
         argz[$i]="${argz[i]#* }"
         sep2=','
      done
      echo -n ")"
      sep1=','
   done
}

FNAMES="John Paul George Ringo"
LNAMES="Lennon McCartney Harrison Starr"
    
sqlite3 people.db "CREATE TABLE people(fname TEXT, lname TEXT);"
sqlite3 people.db "INSERT INTO people(fname, lname) $(MAGIC "$FNAMES" "$LNAMES" ) ;"
sqlite3 people.db -cmd ".mode column" "SELECT * FROM people;"
0
28.07.2021, 11:34

Теги

Похожие вопросы