OpenStack üzerinde çalışan sanal makinelere erişim kuralları iki şekilde tanımlanabilmektedir. Birisi ve en yaygın olarak kullanılanı “security group” denilen güvenlik kuralları vasıtasıyla tanımlanan ve sunucularla ilişkilendirilen mekanizma. Diğeri ise “firewall-as-a-service” olarak geçen ve tanımlanan kuralların projede yer alan tüm sunuculara toptan uygulandığı mekanizma. Bu yazıda ilk bahsedilen Nova güvenlik kurallarının Neutron güvenlik kurallarına taşınması konusu ele alanacaktır. Daha eski sürümlerde Nova API vasıtasıyla tanımlanan kurallar, yeni sürümlerde varsayılan olarak Neutron API vasıtasıyla tanımlanabilmekte, böylece çift yönlü kural tanımlama, port bazında güvenlik gibi avantajlardan faydalanılabilmektedir. Her ne kadar ilgili dokümanda Neutron security group özelliklerinin Nova security group özellikleri ile geriye dönük uyumlu olduğu söylenilse de, Nova security group kullanımından Neutron security group kullanımına geçildiğinde kurallar Neutron’a aktarılmadığı için veritabanı seviyesinde bir taşıma ihtiyacı ortaya çıkmaktadır.
Eğer siz de Nova security group kullanıyor ve Neutron security group kullanmak istiyorsanız aşağıdaki adımları takip ederek mevcut projeler altında daha önce tanımlanan kuralları ilgili projeler altında bağlı oldukları sanal sunucular ile ilişkileri dahil olmak üzere taşıyabilirsiniz.
Öncelikle Nova security group kullanırken Nova ve Neutron yapılandırmaları ilk durumda aşağıdaki gibi olmalıdır. Neutron tarafında ML2 plugin ile openvswitch kullanıldığı varsayılmıştır.
1 2 3 4 5 |
nova.conf: … security_group_api = nova firewall_driver=nova.virt.libvirt.firewall.IptablesFirewallDriver … |
1 2 3 4 5 |
ml2.conf.ini: … [securitygroup] enable_security_group = False ... |
Bu durumda ilgili sanal sunucunun KVM tarafında kullanılan libvirt.xml dosyasında network arayüzü aşağıdaki gibi bağlanmaktadır.
1 2 3 4 5 6 7 8 9 10 |
libvirt.xml: ... <interface type="bridge"> <mac address="fa:16:3e:61:85:c8"/> <model type="virtio"/> <source bridge="qbr12819018-24"/> <target dev="tap12819018-24"/> <filterref filter="nova-instance-instance-000000d6-fa163e6185c8"/> </interface> … |
Neutron security group kullanmak için öncelikle Nova ve Neutron yapılandırmaları aşağıdaki gibi değiştirilmelidir.
1 2 3 4 5 |
nova.conf: … security_group_api = neutron firewall_driver = nova.virt.firewall.NoopFirewallDriver … |
1 2 3 4 5 6 7 |
ml2.conf.ini: … [securitygroup] enable_security_group = True enable_ipset = True firewall_driver = nova.virt.firewall.NoopFirewallDriver ... |
Bu değişikliğin ardından Nova security group kurallarının Neutron veritabanına kopyalanması için yazdığım aşağıdaki Python scriptini kullanabilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# Copyright 2016 # # Author : Huseyin COTUK # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import MySQLdb as mdb import sys import os import time import uuid mysql_host="127.0.0.1" mysql_user="root" mysql_pass="passwd" mysql_db="nova" clear_neutron_sec_grps = True def migrate_secgroup(): try: con = mdb.connect(mysql_host,mysql_user,mysql_pass,mysql_db); cur = con.cursor() if clear_neutron_sec_grps: empty_sec_grp = "delete from neutron.securitygroups" empty_sec_grp_rule = "delete from neutron.securitygrouprules" empty_sec_grp_bind = "delete from neutron.securitygroupportbindings" empty_def_sec_grp = "delete from neutron.default_security_group" cur.execute(empty_sec_grp_bind) cur.fetchall() cur.execute(empty_sec_grp_rule) cur.fetchall() cur.execute(empty_def_sec_grp) cur.fetchall() cur.execute(empty_sec_grp) cur.fetchall() con.commit() cur.execute("SELECT project_id,name,description,id FROM nova.security_groups where deleted=0 and project_id in (select id from keystone.project)") sec_grps = cur.fetchall() for sec_grp in sec_grps: sec_grp_uuid = uuid.uuid4() group_sql = "insert into neutron.securitygroups values ('%s','%s','%s','%s');" %(sec_grp[0],str(sec_grp_uuid),sec_grp[1],sec_grp[2]) cur.execute(group_sql) if sec_grp[1] == 'default': default_sg_sql = "insert into neutron.default_security_group values ('%s','%s');" %(sec_grp[0],str(sec_grp_uuid)) cur.execute(default_sg_sql) rule_sql = "SELECT protocol,from_port,to_port,cidr FROM nova.security_group_rules where deleted=0 and parent_group_id ='%s'" % sec_grp[3] cur.execute(rule_sql) rules = cur.fetchall() for rule in rules: rule_uuid = uuid.uuid4() group_rule_sql = "insert into neutron.securitygrouprules values ('%s','%s','%s',NULL,'ingress','IPv4','%s','%s','%s','%s');" %(sec_grp[0],str(rule_uuid),str(sec_grp_uuid),rule[0],rule[1],rule[2],rule[3]) cur.execute(group_rule_sql) egressv4 = "insert into neutron.securitygrouprules values ('%s','%s','%s',NULL,'egress','IPv4',NULL,NULL,NULL,NULL);" %(sec_grp[0],str(uuid.uuid4()),str(sec_grp_uuid)) egressv6 = "insert into neutron.securitygrouprules values ('%s','%s','%s',NULL,'egress','IPv6',NULL,NULL,NULL,NULL);" %(sec_grp[0],str(uuid.uuid4()),str(sec_grp_uuid)) cur.execute(egressv4) cur.execute(egressv6) instance_sql = "SELECT instance_uuid FROM nova.security_group_instance_association where deleted=0 and security_group_id='%s'" %sec_grp[3] cur.execute(instance_sql) instances = cur.fetchall() for instance in instances: instance_assoc_sql = "SELECT id FROM neutron.ports where device_owner ='compute:nova' and status='active' and tenant_id ='%s' and device_id='%s'" %(sec_grp[0],instance[0]) cur.execute(instance_assoc_sql) ports = cur.fetchall() for port in ports: port_assoc_sql = "insert into neutron.securitygroupportbindings values ('%s','%s');" %(port[0],str(sec_grp_uuid)) cur.execute(port_assoc_sql) con.commit() except mdb.Error, e: print "Error %d: %s" % (e.args[0],e.args[1]) sys.exit(1) finally: if con: con.close() migrate_secgroup() |
Öncelikle scriptin başında yer alan mysql_host, user ve password alanlarını kendinize göre düzenlemeniz gerekmektedir. Hemen altındaki clear_neutron_sec_grps parametresi “True” olduğunda varsa daha önceden Neutron security group altındaki kuralları temizlemeyi sağlamaktadır. Silmek istemezseniz “False” yapabilirsiniz. Scriptin çalışması için Python tarafında MYSQLdb kütüphanesinin tanımlı olması gerekmektedir. Script her proje için dışarıya doğru her protokole izin veren ipv4 ve ipv6 için 2 kural eklemektedir.
Scripti çalıştırdıktan sonra yapılacak iş Nova ve Neutron servislerinin yeniden başlatılmasıdır. Controller, network ve compute node’lar üzerinde bu servisleri başlatmak için aşağıdaki komutları kullanabilirsiniz.
1 2 3 4 5 6 7 8 |
Controller: restart nova-api restart nova-cert restart nova-conductor restart nova-consoleauth restart nova-novncproxy restart nova-scheduler restart neutron-server |
1 2 3 4 5 6 |
Network: restart neutron-plugin-openvswitch-agent restart neutron-dhcp-agent restart neutron-metadata-agent restart neutron-lbaas-agent restart neutron-vpn-agent |
1 2 3 |
Compute: restart nova-compute restart neutron-plugin-openvswitch-agent |
Böylece OpenStack Neutron security group API ile çalışacak hale gelmiştir. Ancak daha önceden başlatılan sanal sunucular oluşurken Nova API ile network arayüzü eklendiği için bu değişikliğin etkili olabilmesi için sanal sunucuların “hard reboot” edilmesi gerekmektedir. Böylece yeni parametreler ile libvirt.xml deosyası yeniden oluşturulacak ve son hali aşağıdaki gibi olacaktır.
1 2 3 4 5 6 7 8 9 10 11 12 |
libvirt.xml: … <interface type="bridge"> <mac address="fa:16:3e:61:85:c8"/> <model type="virtio"/> <source bridge="br-int"/> <target dev="tap12819018-24"/> <virtualport type="openvswitch"> <parameters interfaceid="12819018-24da-460d-a4b8-ca5ef99aa38e"/> </virtualport> </interface> … |
Tüm sanal sunucularda bu işlemi tamamladığınızda Neutron security group Nova üzerinde tanımlanan eski kurallar ile aktif hale gelmiş olacaktır.