Проект Ansible. «Дирижируем» ИТ-инфраструктурой Даниил Прахин # yum install http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm # yum install ansible # cat /etc/ansible/hosts [Workstations] 10.203.96.113 10.203.96.97 [Remote] 10.203.96.113 [Local] localhost remote_tmp = /tmp/.ansible/tmp log_path = /var/log/ansible.log # ansible Workstations –m ping –u root --ask-pwd # 1-я задача для всех ПК группы Remote # файла /etc/ansible/hosts: hosts: Remote # Все хосты в группе Remote remote_user: root # Используем учетную запись root tasks: name: Uptime! # Название задачи «Uptime!» # Модуль: shell, Команда: /usr/bin/uptime shell: /usr/bin/uptime # Сохраняем результат выполнения в переменную result register: result # Модуль: debug, Вывод переменной result debug: var=result # 2-я задача для всех ПК группы Local # файла /etc/ansible/hosts: hosts: Local remote_user: root tasks: # Модуль: user, имя пользователя: tester, # uid: 99999, group: users name: Add the user! user: name=tester comment="This is the Ansible user" uid=99999 group=users # Модуль: yum, имя пакета: xorg-x11-fonts-cyrillic, # состояние: present - установить name: Install the package x11-font! yum: name=xorg-x11-fonts-cyrillic state=present # Модуль: service, имя службы: cups, состояние: stopped name: Stop the CUPS service! service: name=cups state=stopped # 3-я задача для всех ПК группы Workstations # файла /etc/ansible/hosts: hosts: Workstations remote_user: root tasks: # Модуль: script, путь расположения # скрипта на Control Machine: /root/test-pl.pl name: Execute Perl Script! script: /root/test-pl.pl register: result # Модуль: file, путь к файлу: /tmp/test.cfg, # owner, group: sshd, mode: 0173=x-rwx-wx name: Change the File's permissions it it was created file: path=/tmp/test.cfg owner=sshd group=sshd mode=0173 when: result|changed #!/usr/bin/perl open (FILEHANDLE, ">/tmp/test.cfg") or die ("Cannot open the file"); print FILEHANDLE "Hi from Perl!"; close (FILEHANDLE); # ansible-playbook test-playbook.yml --list-tasks --list-hosts # ansible-playbook test-playbook.yml --f 2 --ask-pass # pip install http://github.com/diyan/pywinrm/archive/master.zip#egg=pywinrm ansible_ssh_user: ansible_ssh_pass: ansible_ssh_port: ansible_connection: winrm # ./configure --local # ./setup.sh # service Ansible-tower status ----------------------------------------------------------------------------------------------------------------- Проект Docker. Управляем виртуальными окружениями Денис Силаков # rpm -Uvh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm # yum install docker-io # service docker start # systemctl start docker # docker info # docker run -i -t ubuntu # lsb_release -d # docker run -it ubuntu:14.10 # docker run -it python /bin/bash # docker run -v /tmp:/home/user/tmp ubuntu # docker run --name my_mysql -d mysql # docker run --name my_wordpress --link my_mysql:mysql -d wordpress # docker run -it --name Ubuntu1 ubuntu [inside_container]# apt-get nano # docker commit Ubuntu1 ubuntu_nano # docker save ubuntu_nano > ~/ubuntu_nano.tar # docker load < ~/ubuntu_nano.tar # docker commit Ubuntu1 my_hub_account/ubuntu_nano # docker push my_hub_account/ubuntu_nano FROM ubuntu RUN apt-get nano # docker build -t ubuntu_nano2 ----------------------------------------------------------------------------------------------------------------- Простой менеджмент конфигураций сетевого оборудования Гавриил Каримов # configure terminal # archive # log config # logging enable # write memory # archive # log config # logging enable # hidekeys # exit # path ftp://user:password@IP/$H-$T # write-memory # show archive # set system archival configuration transfer-on-commit # set system archival configuration archive-sites "ftp://user:password@IP-or-Hostname" configuration { transfer-on-commit; archive-sites { "ftp://user:password@IP-or-Hostname"; } } # set system archival configuration transfer-interval 15 # set system archival configuration archive-sites "ftp://user:password@IP-or-Hostname" # pkg search rancid # pkg search rancid rancid-2.3.8_2 rancid3-3.1_1 # pkg install rancid Updating FreeBSD repository catalogue... # pkg install rancid3 LIST_OF_GROUPS="localnet" /etc/aliases: rancid-localnet: localnetadmin1@domain.ru, localnetadmin2@domain.ru rancid-admin-localnet: admin@domain.ru add user *.switch.domain.ru admin add password *.switch.domain.ru {password} {enable_password} add method *.switch.domain.ru ssh cisco.router.domain.ru:cisco:up 192.168.0.2:juniper:up extreme.switch.domain.ru:extreme:down # cat /usr/local/var/rancid/logs/localnet.20150205.084934 #copy ftp://user:password@IP-or-Hostname/filename running-config # edit system archival configuration # load [merge/replace] ftp://user:password@IP-or-Hostname/filename % setenv CVSROOT /usr/local/var/rancid/CVS/ % cd /usr/local/var/rancid/localnet/configs % cvs log hostname.domain.ru % cd /tmp % cvs commit -r 1.2 localnet/configs/hostname.domain.ru ----------------------------------------------------------------------------------------------------------------- Архивариус SCDPM 2012 R2. Часть 2. Защита данных сервера, баз данных, виртуальных машин Сергей Болдин start /WAIT %SystemRoot%\system32\wbadmin.exe start backup -allcritical -quiet -backuptarget:%1 WinRE OS Version: 6.1.7601 Server WinRE Architecture: AMD64 Minimum Number of Disks: 1 Minimum Disk Sizes: Disk 0: 42949017600 bytes (Boot) netsh interface ip set address <имя подключения> static <маска> <метрика шлюза> netsh interface ip set dns <имя подключения> static netsh interface ip set address "Подключение по локальной сети" static 192.168.15.15 255.255.255.0 ----------------------------------------------------------------------------------------------------------------- Управление Google Chrome в корпоративной среде Сергей Яремчук PS> Set-ADFSProperties –ExtendedProtectionTokenCheck None PS> Get-ADFSProperties | Select -ExpandProperty WIASupportedUserAgents PS> Set-ADFSProperties -WIASupportedUserAgents @("MSIE 8.0", MSIE 9.0", "MSIE 10.0", "Trident/7.0", "MSIPC", "Windows Rights Management Client", "Mozilla/5.0") ----------------------------------------------------------------------------------------------------------------- Устройства Arduino для ИТ и ИБ Андрей Бирюков int ledPin = 13; void setup() { pinMode (ledPin, OUTPUT); } void loop() { digitalWrite (ledPin, HIGH); delay (1000); digitalWrite (ledPin, LOW); delay (1000); } void setup() { ... } void loop() { ... } for (int i = 0; i<5; i++) { содержимое цикла } int ledPin = 13; int inPin = 2; void setup() { pinMode (ledPin, OUTPUT); pinMode (inPin, INPUT); } void loop() { if (digitalRead(inPin) == HIGH) { digitalWrite(ledPin, HIGH); delay (1000); } net user имя_пользователя пароль /add net localgroup Administrators имя_пользователя /add ----------------------------------------------------------------------------------------------------------------- Защита SSH от перебора пароля Сергей Яремчук Port 2002 AllowUsers admin user@192.168.0.1 # всем разрешаем доступ по паролю PasswordAuthentication yes # root будет использовать только сертификат match user root PasswordAuthentication no KbdInteractiveAuthentication no sshd : 192.168.1.0/24 : allow sshd : ALL : deny sshd : ALL EXCEPT 192.168.1.0/24 : allow iptables -A INPUT -s !192.168.0.1 -p tcp -m tcp --dport 22 -j REJECT —reject-with icmp-port-unreachable $ sudo apt-get install fail2ban [ssh] enabled = true port = 22 filter = sshd logpath = /var/log/auth.log maxretry = 3 ----------------------------------------------------------------------------------------------------------------- Детект уязвимости CVE-2014-8609. Sine ira et studio Александр Свириденко private static final String SHOULD_NOT_RESOLVE = "SHOULDN'T RESOLVE!" private void addAccount(String accountType) { .... v8.setComponent(new ComponentName("SHOULDN\'T RESOLVE!", "SHOULDN\'T RESOLVE!")); v8.setAction("SHOULDN\'T RESOLVE!"); v8.addCategory("SHOULDN\'T RESOLVE!"); public static boolean a() { int v0 = w.a(); boolean v0_1 = 401 > v0 || v0 > 444 ? false : true; return v0_1; } ----------------------------------------------------------------------------------------------------------------- Handler Socket в кластере Александр Календарев HANDLER tbl_name OPEN [[AS] alias] // открываем хандлер // читаем данные HANDLER tbl_name READ index_name {=|<=|>=|<|>} (value1,value2,...) [ WHERE where_condition ] [LIMIT ... ] HANDLER tbl_name READ index_name {FIRST|NEXT|PREV|LAST} HANDLER tbl_name CLOSE // закрываем хандлер P [номер индекса] [имя БД] [имя таблицы] [имя индекса] [список полей через запятую] akalend.local 9998 P 0 testDb users PRIMARY user_id,name [номер индекса] [операция] [кол-во данных] [данные key1] [ [данные key2]...] [ [limit] [ [IN] [filter] ]] ... 0 = 1 123123 0 2 123123 Alexandre void time_start(struct timeval *tv){ gettimeofday(tv, NULL); } long time_stop(struct timeval *tv){ struct timeval tv2; gettimeofday(&tv2, NULL); long sec= tv2.tv_sec - tv->tv_sec; long usec=tv2.tv_usec - tv->tv_usec; if(usec < 0) { sec--; usec += 1000000; } return sec * 1000000 + usec; } ... struct timeval tv; char query[128]; int user_id = 1234567; sprintf(query,"SELECT user_id,name FROM users WHERE user_id=%s", user_id); /* код по открытию соединения с MySQL пропущен */ time_start(&tv); mysql_real_query(mysql,query); long t = time_stop(&tv); mysql_close(mysql); printf("MySQL time %ld\n", t); ... /* код по созданию сокета и открытию соединения пропущен */ char buf[4098]; const char* index_string="P\t0\ttestDb\tusers\tPRIMARY\tuser_id,name\n"; const char* query_string="0\t=\t1\t%d\n"; int query_len = sprintf(query, query_string, user_id); // операция открытия индекса time_start(&tv); write(hs_fd, index_string, sizeof(index_string-1)); len= read(hs_fd, buf, 4098); if (len != 3 || buf[0] != '0') { // здесь код анализа ошибки } // операция выполнения запроса данных write(hs_fd, query, query_len); len= read(hs_fd, buf, 4098); if (buf[0] != '0') { // здесь код анализа ошибки } t = time_stop(&tv); close(hs_fd); printf("HS time %ld\n", t); // операция выполнения запроса данных time_start(&tv); write(hs_fd, query, query_len); len= read(hs_fd, buf, 4098); if (buf[0] != '0') { // код анализа ошибки } t = time_stop(&tv); // LOCK FREE структуры для индивидуального доступа // потока к данным #define HS_LOCK(cd,i) \ while(!__sync_bool_compare_and_swap(&cd->hs[(i)].lock, 0,1)){usleep(1);} #define HS_UNLOCK(cd,i) \ __sync_lock_test_and_set(&cd->hs[i].lock, 0); struct { fd; // файловый дескриптор пула int buzy; // состояние – 1 дескриптор занят } hs_t; typedef struct hs_t hs_t; struct { // количество открытых деcкрипторов в пуле hs_count; hs_t *hs; // ссылка на массив структур hs int lock; // lock переменная } hs_pool_t; typedef struct hs_pool_t hs_pool_t; static int hs_get_pool(struct hs_pool_t* cd){ int i; int res = ERR; for(i = 0; i < cd->hs_count; i++){ if (!cd->hs[i].fd) { printf("socket id=%d closed\n", i); continue; } HS_LOCK(cd, i); // т.к. имеем дело с многопоточностью, необходим LOCK if (cd->hs[i].buzy) { // если дескриптор занят, то ищем следующий свободный HS_UNLOCK(cd,i); continue; } cd->hs[i].buzy = 1; // нашли свободный дескриптор, помечаем как занятый HS_UNLOCK(cd,i); res = i; break; } return res; } static void hs_put_pool(struct conn_desc* cd, int id) { HS_LOCK(cd, id); cd->hs[id].buzy = 0; HS_UNLOCK(cd, id); } struct obuffer { union { const char *c_data; const uint8_t *u_data; const void *data; }; bsize_t pos; bsize_t length; }; void obuffer_init(struct obuffer *b, const void *data, bsize_t size) { b->data = data; b->pos = 0; b->length = size; } int obuffer_send(struct obuffer *b, int fd) { while (b->pos < b->length) { ssize_t bytes = write(fd, b->u_data + b->pos, b->length - b->pos); if (bytes > 0) { b->pos += bytes; } else { if (errno == EAGAIN) break; if (errno == EINTR) continue; return -1; } } return b->length - b->pos; } static int read_nb(int fd, char* buff, int size) { int len = 0; int counter=0; while (len < size) { counter++; ssize_t bytes = read(fd, buff + len, size - len ); if (bytes > 0) { if (len + bytes > size) { syslog(LOG_ERR, "%s reciive bytes %d more than BUFSIZE", __FUNCTION__, (int)bytes); return ERR; } len += bytes; // последний прочтенный символ \n if (*(buff+len-1) == '\n') { return OK; } } else if(bytes == ERR){ if (errno == EINTR) continue; if (errno == EAGAIN) { if ( counter > 200 * 5) { // 5 ms syslog(LOG_ERR, "EAGAIN counter=%d", counter); return ERR; } usleep(5); continue; }; // прочие ошибки syslog(LOG_ERR, "надо переоткрыть сокет"); return ERR; } else { // ничего не прочли if ( counter > 200 * 5) { // 5 ms syslog(LOG_ERR, "read timeout counter=%d len=%d", counter, len); return ERR; } usleep(5); continue; } } return OK; } main() { struct ev_loop *loop; loop = ev_loop_new(0); // присоединяем к event_loop файловый дескриптор HS ev_io hs_io; ev_io_init( &hs_io, on_hs_read, fd_hs, EV_READ); ev_io_start( loop, &hs_io); // запуск loop цикла ev_loop(loop, 0); } /* данная сопрограмма вызовется, когда на сокет thread->fd будет готов для чтения. */ static void on_hs_read (void * data) { thread_t* thread = (thread_t *) data; thread->ret = OK; if (read_nb(thread ->fd,thread ->buff, thread ->buff_size) == ERR) { syslog(LOG_ERR,"read HS error: %s\n", strerror(errno)); thread->ret = ERR; } else { if ( *buff != '0' || *(buff+1) != '\t' || *(buff+2) != '1' ) { thread->ret = ERR; } } // по окончании чтения мы передаем сопрограмме // флаг на продолжение. pch_resume(thread); } static int hs_open_index( thread_t, thread, const int index_id, char* db_name, char* table, char* index, char* colums) { char buff[1024]; int len = sprintf(buff,"P\t%d\t%s\t%s\t%s\t%s\n", index_id, db_name, table, index, colums); struct obuffer o_buff; obuffer_init(&o_buff, buff, len); if ( obuffer_send(&o_buff, thread->fd) == ERR){ if (errno == EPIPE) { syslog(LOG_ERR, "надо переоткрыть сокет"); return ERR; } syslog(LOG_ERR, "write HS error: %s\n", strerror(errno)); return ERR; } // тут мы прерываем выполнение сопрограммы, // передается управление другой cопрограмме pch_yield(thread); return OK; static user_t* hs_get_user(uint32_t uid){ // должны точно знать максимальный размер объекта char buff[1024]; int size = sizeof(buff); struct obuffer o_buff; struct conn_desc * cd = (struct conn_desc*) &cfg_db->cds; // вычисляем номер дескриптора int pool_id = hs_get_pool(cd); if (pool_id == ERR) { syslog(LOG_ERR, "all hs pool is closed"); return ERR; } // берем соответствующий дескриптор из пула hs_conn_t* hs = &cd->hs[pool_id]; int fd = hs->fd; // подготавливаем данные для вывода в Handler Socket int len = sprintf( buff, "%d\t=\t1\t%u\n", hs_shard_idx, uid); // пересылаем данные obuffer_init( &o_buff, buff, len); if ( obuffer_send(&o_buff, fd) == ERR){ // что-то не так с выводом, закрываем дескриптор close(fd); // зануляем, далее потом переоткроем по таймеру. hs->fd = 0; return ERR; } bzero(buff, size); // читаем данные в буфер if (read_nb(fd,buff,size) == ERR) { // что-то не так с вводом, закрываем дескриптор close(fd); // зануляем, далее потом переоткроем по таймеру. hs->fd = 0; return ERR; } // возвращаем дескриптор в пул hs_put_pool(cd, pool_id); int shard_id = ERR, state = ERR; char name[64]; // ниже идет парсинг и анализ результата if (3 != sscanf( buff, "0\t1\t%d\t%d\t%s", &shard_id, &state, &name )) { if (*buff == '0' && *(buff+2)=='1') { // ничего не найдено количество аргументов scanf = 2 bzero(buff,len); return NULL_RES; } else { // скорее всего *buff != '0' printf("error parse result\n"); // первый байт = код возврата bzero(buff,len); // 1 или 2 – ошибка return ERR; } // все удачно: выделяем память и присваиваем данные user_t* user = (user_t*)calloc(1, sizeof(user_t)); user->state = state; user->uid = uid; user->name = strdup(name); return user; } return NULL; } ----------------------------------------------------------------------------------------------------------------- Внедряем «Луну» Константин Рачаев lua_newtable(L); lua_pushstring(L, "key"); lua_pushnumber(L, value); lua_settable(L, -3); // Указывает на таблицу lua_newtable(L); lua_pushnumber(L, value); lua_setfield(L, -2, "key"); lua_getglobal(L, "table"); lua_getfield(L, -1, "key"); int main (void) { lua_State *L = luaL_newstate(); /* create state */ if (L == NULL) { fprintf(stderr, "%s\n", "cannot create state: not enough memory"); return EXIT_FAILURE; } openlibs(L); int status = luaL_loadfile(L, script_name); if(status != LUA_OK) { error_msg(L); } // call in protected mode status = lua_pcall(L, 0, 0, 0); if(status != LUA_OK) { error_msg(L); } // Setup init parameters by default init_param_t init_param; init_param.speed = 0; init_param.motion_lua_func = "none"; if(setup_init_param(L, init_param) != 0) { fprintf(stderr, "%s\n", "cannot initialize parameters"); return EXIT_FAILURE; } printf("speed: %d\n", init_param.speed); printf("motion_lua_func: %s\n", init_param.motion_lua_func.c_str()); lua_getglobal(L, init_param.motion_lua_func.c_str()); // call in protected mode; 0 arg, 1 result status = lua_pcall(L, 0, 1, 0); if(status != LUA_OK) { error_msg(L); return EXIT_FAILURE; } int scan_res = lua_tonumber(L, -1); /* 1 result */ printf("Analyse scanning result: %d\n", scan_res); lua_close(L); return EXIT_SUCCESS; } #include #define LUA_LIB #include "lua.h" static int librobot_rightturn(lua_State *L) { printf("rightturn\n"); return 0; } static int librobot_scanning(lua_State *L) { time_t t; printf("scanning\n"); srand((unsigned) time(&t)); lua_pushnumber(L, rand()%2); return 1; } static const luaL_Reg librobot[] = { {"print_char", librobot_printchar}, {"sleep", librobot_sleep}, {"forward", librobot_forward}, {"backward", librobot_backward}, {"leftturn", librobot_leftturn}, {"rightturn", librobot_rightturn}, {"scanning", librobot_scanning}, {NULL, NULL} }; LUAMOD_API int luaopen_robot(lua_State *L) { luaL_newlib(L, librobot); return 1; } typedef struct luaL_Reg { const char *name; lua_CFunction func; } luaL_Reg;