Add bandit for security static analysis and fix potential security issues
This change adds a basic bandit config for cloudkitty. It can be invoked by running the tox environment for bandit; tox -e bandit These changes also fix potential security issues find during bandit checks. - binding to all interface: remove useless host_ip option to avoid issue - hash function issue: switch from sha1 to sha512 - use of exec: can't be removed for moment so using #nosec comment Change-Id: Iae7d7604457345fe6d482cf48311c9b75fdde947
This commit is contained in:
parent
7c7ff81cd9
commit
60740282c9
.zuul.yaml
cloudkitty
lower-constraints.txtreleasenotes/notes
test-requirements.txttox.ini
24
.zuul.yaml
24
.zuul.yaml
@ -40,6 +40,28 @@
|
|||||||
DEVSTACK_GATE_USE_PYTHON3: "True"
|
DEVSTACK_GATE_USE_PYTHON3: "True"
|
||||||
USE_PYTHON3: "True"
|
USE_PYTHON3: "True"
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: cloudkitty-tox-bandit
|
||||||
|
parent: openstack-tox
|
||||||
|
timeout: 2400
|
||||||
|
vars:
|
||||||
|
tox_envlist: bandit
|
||||||
|
required-projects:
|
||||||
|
- openstack/requirements
|
||||||
|
irrelevant-files:
|
||||||
|
- ^.*\.rst$
|
||||||
|
- ^.*\.txt$
|
||||||
|
- ^api-ref/.*$
|
||||||
|
- ^apidocs/.*$
|
||||||
|
- ^contrib/.*$
|
||||||
|
- ^doc/.*$
|
||||||
|
- ^etc/.*$
|
||||||
|
- ^releasenotes/.*$
|
||||||
|
- ^setup.cfg$
|
||||||
|
- ^tools/.*$
|
||||||
|
- ^cloudkitty/hacking/.*$
|
||||||
|
- ^cloudkitty/tests/scenario/.*$
|
||||||
|
- ^cloudkitty/tests/unittests/.*$
|
||||||
|
|
||||||
- project:
|
- project:
|
||||||
templates:
|
templates:
|
||||||
@ -55,6 +77,8 @@
|
|||||||
jobs:
|
jobs:
|
||||||
- cloudkitty-tempest-full
|
- cloudkitty-tempest-full
|
||||||
- cloudkitty-tempest-full-python3
|
- cloudkitty-tempest-full-python3
|
||||||
|
- cloudkitty-tox-bandit:
|
||||||
|
voting: false
|
||||||
gate:
|
gate:
|
||||||
queue: cloudkitty
|
queue: cloudkitty
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -42,9 +42,6 @@ auth_opts = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
api_opts = [
|
api_opts = [
|
||||||
cfg.IPOpt('host_ip',
|
|
||||||
default='0.0.0.0',
|
|
||||||
help='The listen IP for the cloudkitty API server.'),
|
|
||||||
cfg.PortOpt('port',
|
cfg.PortOpt('port',
|
||||||
default=8889,
|
default=8889,
|
||||||
help='The port for the cloudkitty API server.'),
|
help='The port for the cloudkitty API server.'),
|
||||||
|
@ -77,7 +77,7 @@ class PyScripts(rating.RatingProcessorBase):
|
|||||||
|
|
||||||
def start_script(self, code, data):
|
def start_script(self, code, data):
|
||||||
context = {'data': data}
|
context = {'data': data}
|
||||||
exec(code, context)
|
exec(code, context) # nosec
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def process(self, data):
|
def process(self, data):
|
||||||
|
@ -42,7 +42,9 @@ class Script(wtypes.Base):
|
|||||||
sample = cls(script_id='bc05108d-f515-4984-8077-de319cbf35aa',
|
sample = cls(script_id='bc05108d-f515-4984-8077-de319cbf35aa',
|
||||||
name='policy1',
|
name='policy1',
|
||||||
data='return 0',
|
data='return 0',
|
||||||
checksum='da39a3ee5e6b4b0d3255bfef95601890afd80709')
|
checksum='cf83e1357eefb8bdf1542850d66d8007d620e4050b5715d'
|
||||||
|
'c83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec'
|
||||||
|
'2f63b931bd47417a81a538327af927da3e')
|
||||||
return sample
|
return sample
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
# Copyright 2019 OpenStack Foundation
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""move from sha1 to sha512
|
||||||
|
|
||||||
|
Revision ID: 75c205f6f1a2
|
||||||
|
Revises: 4f9efa4601c0
|
||||||
|
Create Date: 2019-03-25 13:53:23.398755
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '75c205f6f1a2'
|
||||||
|
down_revision = '4f9efa4601c0'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
with op.batch_alter_table('pyscripts_scripts') as batch_op:
|
||||||
|
batch_op.alter_column('checksum',
|
||||||
|
existing_type=sa.VARCHAR(length=40),
|
||||||
|
type_=sa.String(length=128))
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
with op.batch_alter_table('pyscripts_scripts') as batch_op:
|
||||||
|
batch_op.alter_column('checksum',
|
||||||
|
existing_type=sa.String(length=128),
|
||||||
|
type_=sa.VARCHAR(length=40))
|
@ -82,7 +82,7 @@ class PyScriptsScript(Base, PyScriptsBase):
|
|||||||
sqlalchemy.LargeBinary(),
|
sqlalchemy.LargeBinary(),
|
||||||
nullable=False)
|
nullable=False)
|
||||||
_checksum = sqlalchemy.Column('checksum',
|
_checksum = sqlalchemy.Column('checksum',
|
||||||
sqlalchemy.String(40),
|
sqlalchemy.String(128),
|
||||||
nullable=False)
|
nullable=False)
|
||||||
|
|
||||||
@hybrid.hybrid_property
|
@hybrid.hybrid_property
|
||||||
@ -92,7 +92,7 @@ class PyScriptsScript(Base, PyScriptsBase):
|
|||||||
|
|
||||||
@data.setter
|
@data.setter
|
||||||
def data(self, value):
|
def data(self, value):
|
||||||
sha_check = hashlib.sha1()
|
sha_check = hashlib.sha512()
|
||||||
sha_check.update(value)
|
sha_check.update(value)
|
||||||
self._checksum = sha_check.hexdigest()
|
self._checksum = sha_check.hexdigest()
|
||||||
self._data = zlib.compress(value)
|
self._data = zlib.compress(value)
|
||||||
|
@ -38,7 +38,7 @@ tests:
|
|||||||
$.script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
$.script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
||||||
$.name: "policy1"
|
$.name: "policy1"
|
||||||
$.data: "a = 0"
|
$.data: "a = 0"
|
||||||
$.checksum: "5ae340c1b3bb81955db1cb593cdc78540082c526"
|
$.checksum: "4c612e33c0e40b7bf53cf95fad47dbfbeab9dd62f9bc181a9d1c6f40a087782223c23f793e747b0466b9e6998c6ea54f4edbd20febd13edb13b55074b5ee1a5a"
|
||||||
response_headers:
|
response_headers:
|
||||||
location: '$SCHEME://$NETLOC/v1/rating/module_config/pyscripts/scripts/6c1b8a30-797f-4b7e-ad66-9879b79059fb'
|
location: '$SCHEME://$NETLOC/v1/rating/module_config/pyscripts/scripts/6c1b8a30-797f-4b7e-ad66-9879b79059fb'
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ tests:
|
|||||||
$.scripts[0].script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
$.scripts[0].script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
||||||
$.scripts[0].name: "policy1"
|
$.scripts[0].name: "policy1"
|
||||||
$.scripts[0].data: "a = 0"
|
$.scripts[0].data: "a = 0"
|
||||||
$.scripts[0].checksum: "5ae340c1b3bb81955db1cb593cdc78540082c526"
|
$.scripts[0].checksum: "4c612e33c0e40b7bf53cf95fad47dbfbeab9dd62f9bc181a9d1c6f40a087782223c23f793e747b0466b9e6998c6ea54f4edbd20febd13edb13b55074b5ee1a5a"
|
||||||
|
|
||||||
- name: list scripts excluding data
|
- name: list scripts excluding data
|
||||||
url: /v1/rating/module_config/pyscripts/scripts?no_data=true
|
url: /v1/rating/module_config/pyscripts/scripts?no_data=true
|
||||||
@ -70,7 +70,7 @@ tests:
|
|||||||
response_json_paths:
|
response_json_paths:
|
||||||
$.scripts[0].script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
$.scripts[0].script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
||||||
$.scripts[0].name: "policy1"
|
$.scripts[0].name: "policy1"
|
||||||
$.scripts[0].checksum: "5ae340c1b3bb81955db1cb593cdc78540082c526"
|
$.scripts[0].checksum: "4c612e33c0e40b7bf53cf95fad47dbfbeab9dd62f9bc181a9d1c6f40a087782223c23f793e747b0466b9e6998c6ea54f4edbd20febd13edb13b55074b5ee1a5a"
|
||||||
|
|
||||||
- name: get script
|
- name: get script
|
||||||
url: /v1/rating/module_config/pyscripts/scripts/6c1b8a30-797f-4b7e-ad66-9879b79059fb
|
url: /v1/rating/module_config/pyscripts/scripts/6c1b8a30-797f-4b7e-ad66-9879b79059fb
|
||||||
@ -79,7 +79,7 @@ tests:
|
|||||||
$.script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
$.script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
||||||
$.name: "policy1"
|
$.name: "policy1"
|
||||||
$.data: "a = 0"
|
$.data: "a = 0"
|
||||||
$.checksum: "5ae340c1b3bb81955db1cb593cdc78540082c526"
|
$.checksum: "4c612e33c0e40b7bf53cf95fad47dbfbeab9dd62f9bc181a9d1c6f40a087782223c23f793e747b0466b9e6998c6ea54f4edbd20febd13edb13b55074b5ee1a5a"
|
||||||
|
|
||||||
- name: modify script
|
- name: modify script
|
||||||
url: /v1/rating/module_config/pyscripts/scripts/6c1b8a30-797f-4b7e-ad66-9879b79059fb
|
url: /v1/rating/module_config/pyscripts/scripts/6c1b8a30-797f-4b7e-ad66-9879b79059fb
|
||||||
@ -95,7 +95,7 @@ tests:
|
|||||||
$.script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
$.script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
||||||
$.name: "policy1"
|
$.name: "policy1"
|
||||||
$.data: "a = 1"
|
$.data: "a = 1"
|
||||||
$.checksum: "b88f1ec0c9fe96fde96a6f9dabcbeee661dd7afe"
|
$.checksum: "acb3095e24b13960484e75bce070e13e8a7728760517c31b34929a6f732841c652e9d2cc4d186bd02ef2e7495fab3c4850673bedc945cee7c74fea85eabd542c"
|
||||||
|
|
||||||
- name: modify unknown script
|
- name: modify unknown script
|
||||||
url: /v1/rating/module_config/pyscripts/scripts/42
|
url: /v1/rating/module_config/pyscripts/scripts/42
|
||||||
@ -120,7 +120,7 @@ tests:
|
|||||||
$.script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
$.script_id: "6c1b8a30-797f-4b7e-ad66-9879b79059fb"
|
||||||
$.name: "policy1"
|
$.name: "policy1"
|
||||||
$.data: "a = 1"
|
$.data: "a = 1"
|
||||||
$.checksum: "b88f1ec0c9fe96fde96a6f9dabcbeee661dd7afe"
|
$.checksum: "acb3095e24b13960484e75bce070e13e8a7728760517c31b34929a6f732841c652e9d2cc4d186bd02ef2e7495fab3c4850673bedc945cee7c74fea85eabd542c"
|
||||||
|
|
||||||
- name: delete script
|
- name: delete script
|
||||||
url: /v1/rating/module_config/pyscripts/scripts/6c1b8a30-797f-4b7e-ad66-9879b79059fb
|
url: /v1/rating/module_config/pyscripts/scripts/6c1b8a30-797f-4b7e-ad66-9879b79059fb
|
||||||
|
@ -84,11 +84,11 @@ CK_RESOURCES_DATA = [{
|
|||||||
"unit": "instance"}}]}}]
|
"unit": "instance"}}]}}]
|
||||||
|
|
||||||
TEST_CODE1 = 'a = 1'.encode('utf-8')
|
TEST_CODE1 = 'a = 1'.encode('utf-8')
|
||||||
TEST_CODE1_CHECKSUM = hashlib.sha1(TEST_CODE1).hexdigest()
|
TEST_CODE1_CHECKSUM = hashlib.sha512(TEST_CODE1).hexdigest()
|
||||||
TEST_CODE2 = 'a = 0'.encode('utf-8')
|
TEST_CODE2 = 'a = 0'.encode('utf-8')
|
||||||
TEST_CODE2_CHECKSUM = hashlib.sha1(TEST_CODE2).hexdigest()
|
TEST_CODE2_CHECKSUM = hashlib.sha512(TEST_CODE2).hexdigest()
|
||||||
TEST_CODE3 = 'if a == 1: raise Exception()'.encode('utf-8')
|
TEST_CODE3 = 'if a == 1: raise Exception()'.encode('utf-8')
|
||||||
TEST_CODE3_CHECKSUM = hashlib.sha1(TEST_CODE3).hexdigest()
|
TEST_CODE3_CHECKSUM = hashlib.sha512(TEST_CODE3).hexdigest()
|
||||||
|
|
||||||
COMPLEX_POLICY1 = """
|
COMPLEX_POLICY1 = """
|
||||||
import decimal
|
import decimal
|
||||||
@ -238,7 +238,8 @@ class PyScriptsRatingTest(tests.TestCase):
|
|||||||
setattr,
|
setattr,
|
||||||
script,
|
script,
|
||||||
'checksum',
|
'checksum',
|
||||||
'da39a3ee5e6b4b0d3255bfef95601890afd80709')
|
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce4'
|
||||||
|
'7d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e')
|
||||||
|
|
||||||
def test_update_checksum(self):
|
def test_update_checksum(self):
|
||||||
self._db_api.create_script('policy1', TEST_CODE1)
|
self._db_api.create_script('policy1', TEST_CODE1)
|
||||||
|
@ -45,3 +45,4 @@ reno==1.8.0 # Apache2
|
|||||||
sphinxcontrib-httpdomain==1.6.0 # Apache-2.0
|
sphinxcontrib-httpdomain==1.6.0 # Apache-2.0
|
||||||
doc8==0.6.0 # Apache-2.0
|
doc8==0.6.0 # Apache-2.0
|
||||||
Pygments==2.2.0 # BSD
|
Pygments==2.2.0 # BSD
|
||||||
|
bandit==1.1.0 # Apache-2.0
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
security:
|
||||||
|
- |
|
||||||
|
Introduce bandit security checks and fix potential security issues detected
|
||||||
|
by bandit linter. Remove unused option where host_ip was a binding to all
|
||||||
|
interfaces. Using of insecure hash function, switch from sha1 to sha512.
|
@ -20,3 +20,4 @@ sphinxcontrib-pecanwsme>=0.8 # Apache-2.0
|
|||||||
reno>=1.8.0 # Apache-2.0
|
reno>=1.8.0 # Apache-2.0
|
||||||
doc8>=0.6.0 # Apache-2.0
|
doc8>=0.6.0 # Apache-2.0
|
||||||
Pygments>=2.2.0 # BSD license
|
Pygments>=2.2.0 # BSD license
|
||||||
|
bandit>=1.1.0 # Apache-2.0
|
||||||
|
5
tox.ini
5
tox.ini
@ -27,6 +27,11 @@ commands =
|
|||||||
flake8 {posargs} cloudkitty
|
flake8 {posargs} cloudkitty
|
||||||
doc8 {posargs}
|
doc8 {posargs}
|
||||||
|
|
||||||
|
[testenv:bandit]
|
||||||
|
basepython = python3
|
||||||
|
deps = -r{toxinidir}/test-requirements.txt
|
||||||
|
commands = bandit -r cloudkitty -n5 -x tests -ll
|
||||||
|
|
||||||
[testenv:cover]
|
[testenv:cover]
|
||||||
basepython = python3
|
basepython = python3
|
||||||
setenv =
|
setenv =
|
||||||
|
Loading…
Reference in New Issue
Block a user