Merge "Add audit"
This commit is contained in:
commit
d33ce42512
|
@ -0,0 +1,91 @@
|
|||
#
|
||||
# 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 logging
|
||||
|
||||
from pycadf import cadftaxonomy
|
||||
from pycadf import event
|
||||
from pycadf import identifier
|
||||
from pycadf import resource
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _emit_event(ev):
|
||||
# no actual implementation yet
|
||||
if not ev.is_valid():
|
||||
logger.error("created invalid audit event: %s", ev)
|
||||
|
||||
|
||||
def _event_defaults(result):
|
||||
# eventType, id, eventTime are filled in automatically by pyCADF
|
||||
return {
|
||||
'outcome': (cadftaxonomy.OUTCOME_SUCCESS if result else
|
||||
cadftaxonomy.OUTCOME_FAILURE),
|
||||
}
|
||||
|
||||
|
||||
def _user_resource(username):
|
||||
return resource.Resource(
|
||||
# TODO(stan): generate id from username if it's known
|
||||
# this should also get username from keystone tokens to work correctly
|
||||
id=identifier.generate_uuid(),
|
||||
typeURI=cadftaxonomy.ACCOUNT_USER,
|
||||
name=username)
|
||||
|
||||
|
||||
def _auth_resource(ra_name):
|
||||
return resource.Resource(
|
||||
id='anchor://authentication',
|
||||
typeURI=cadftaxonomy.SERVICE_SECURITY,
|
||||
domain=ra_name)
|
||||
|
||||
|
||||
def _policy_resource(ra_name):
|
||||
return resource.Resource(
|
||||
id='anchor://certificates/policy',
|
||||
typeURI=cadftaxonomy.SECURITY_POLICY,
|
||||
domain=ra_name)
|
||||
|
||||
|
||||
def _certificate_resource(fingerprint):
|
||||
if fingerprint is None:
|
||||
res_id = identifier.generate_uuid()
|
||||
else:
|
||||
res_id = "certificate:%s" % (fingerprint,)
|
||||
return resource.Resource(
|
||||
id=res_id,
|
||||
typeURI=cadftaxonomy.SECURITY_KEY,
|
||||
)
|
||||
|
||||
|
||||
def emit_auth_event(ra_name, username, result):
|
||||
params = _event_defaults(result)
|
||||
params['action'] = 'authenticate'
|
||||
params['initiator'] = _user_resource(username)
|
||||
auth_res = _auth_resource(ra_name)
|
||||
params['observer'] = auth_res
|
||||
params['target'] = auth_res
|
||||
_emit_event(event.Event(**params))
|
||||
|
||||
|
||||
def emit_signing_event(ra_name, username, result, fingerprint=None):
|
||||
params = _event_defaults(result)
|
||||
params['action'] = 'evaluate'
|
||||
params['initiator'] = _user_resource(username)
|
||||
params['observer'] = _policy_resource(ra_name)
|
||||
params['target'] = _certificate_resource(fingerprint)
|
||||
# add when pycadf merges event names
|
||||
# params['name'] = "certificate signing"
|
||||
_emit_event(event.Event(**params))
|
|
@ -123,8 +123,8 @@ def dispatch_sign(ra_name, csr):
|
|||
logger.exception("Failed to sign the certificate")
|
||||
pecan.abort(500, "certificate signing error")
|
||||
|
||||
fingerprint = certificate_fingerprint(cert_pem, 'sha256')
|
||||
if ca_conf.get('output_path') is not None:
|
||||
fingerprint = certificate_fingerprint(cert_pem, 'sha256')
|
||||
path = os.path.join(
|
||||
ca_conf['output_path'],
|
||||
'%s.crt' % fingerprint)
|
||||
|
@ -134,7 +134,7 @@ def dispatch_sign(ra_name, csr):
|
|||
with open(path, "w") as f:
|
||||
f.write(cert_pem)
|
||||
|
||||
return cert_pem
|
||||
return cert_pem, fingerprint
|
||||
|
||||
|
||||
def _run_fixup(name, body, args):
|
||||
|
|
|
@ -15,7 +15,9 @@ import logging
|
|||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from webob import exc as http_status
|
||||
|
||||
from anchor import audit
|
||||
from anchor import auth
|
||||
from anchor import certificate_ops
|
||||
from anchor import jsonloader
|
||||
|
@ -46,15 +48,32 @@ class SignInstanceController(GenericInstanceController):
|
|||
|
||||
logger.debug("processing signing request in registration authority %s",
|
||||
ra_name)
|
||||
auth_result = auth.validate(ra_name,
|
||||
pecan.request.POST.get('user'),
|
||||
pecan.request.POST.get('secret'))
|
||||
csr = certificate_ops.parse_csr(pecan.request.POST.get('csr'),
|
||||
pecan.request.POST.get('encoding'))
|
||||
certificate_ops.validate_csr(ra_name, auth_result, csr, pecan.request)
|
||||
csr = certificate_ops.fixup_csr(ra_name, csr, pecan.request)
|
||||
try:
|
||||
auth_result = auth.validate(ra_name,
|
||||
pecan.request.POST.get('user'),
|
||||
pecan.request.POST.get('secret'))
|
||||
audit.emit_auth_event(ra_name, pecan.request.POST.get('user'),
|
||||
True)
|
||||
except http_status.HTTPUnauthorized:
|
||||
audit.emit_auth_event(ra_name, pecan.request.POST.get('user'),
|
||||
False)
|
||||
raise
|
||||
|
||||
return certificate_ops.dispatch_sign(ra_name, csr)
|
||||
try:
|
||||
csr = certificate_ops.parse_csr(pecan.request.POST.get('csr'),
|
||||
pecan.request.POST.get('encoding'))
|
||||
certificate_ops.validate_csr(ra_name, auth_result, csr,
|
||||
pecan.request)
|
||||
csr = certificate_ops.fixup_csr(ra_name, csr, pecan.request)
|
||||
|
||||
cert, fingerprint = certificate_ops.dispatch_sign(ra_name, csr)
|
||||
audit.emit_signing_event(ra_name, pecan.request.POST.get('user'),
|
||||
True, fingerprint=fingerprint)
|
||||
except Exception:
|
||||
audit.emit_signing_event(ra_name, pecan.request.POST.get('user'),
|
||||
False)
|
||||
raise
|
||||
return cert
|
||||
|
||||
|
||||
class CAInstanceController(GenericInstanceController):
|
||||
|
|
|
@ -10,3 +10,4 @@ netaddr!=0.7.16,>=0.7.12
|
|||
ldap3>=0.9.8.2 # LGPLv3
|
||||
requests!=2.8.0,>=2.5.2
|
||||
stevedore>=1.5.0 # Apache-2.0
|
||||
pycadf>=1.1.0
|
||||
|
|
Loading…
Reference in New Issue