# Authors:
#     Christina Fu <cfu@redhat.com>
#
# Copyright Red Hat, Inc.
#
# SPDX-License-Identifier: GPL-2.0-or-later

from __future__ import absolute_import
import logging
import os
import shutil

import pki

logger = logging.getLogger(__name__)


class AddProfileCaAuditSigningCert(pki.server.upgrade.PKIServerUpgradeScriptlet):

    caAuditSigningCert = """desc=This certificate profile is for enrolling audit signing certificates.
visible=true
enable=true
enableBy=admin
auth.instance_id=
authz.acl=group="Enterprise OCSP Administrators" || group="Enterprise RA Administrators" || group="Enterprise CA Administrators" || group="Enterprise KRA Administrators" || group="Enterprise TKS Administrators" || group="Enterprise TPS Administrators"
name=Manual Audit Signing Certificate Enrollment
input.list=i1,i2
input.i1.class_id=certReqInputImpl
input.i2.class_id=submitterInfoInputImpl
output.list=o1
output.o1.class_id=certOutputImpl
policyset.list=auditSigningCertSet
policyset.auditSigningCertSet.list=1,2,3,4,5,6,9
policyset.auditSigningCertSet.1.constraint.class_id=subjectNameConstraintImpl
policyset.auditSigningCertSet.1.constraint.name=Subject Name Constraint
policyset.auditSigningCertSet.1.constraint.params.pattern=CN=.*
policyset.auditSigningCertSet.1.constraint.params.accept=true
policyset.auditSigningCertSet.1.default.class_id=userSubjectNameDefaultImpl
policyset.auditSigningCertSet.1.default.name=Subject Name Default
policyset.auditSigningCertSet.1.default.params.name=
policyset.auditSigningCertSet.2.constraint.class_id=validityConstraintImpl
policyset.auditSigningCertSet.2.constraint.name=Validity Constraint
policyset.auditSigningCertSet.2.constraint.params.range=720
policyset.auditSigningCertSet.2.constraint.params.notBeforeCheck=false
policyset.auditSigningCertSet.2.constraint.params.notAfterCheck=false
policyset.auditSigningCertSet.2.default.class_id=validityDefaultImpl
policyset.auditSigningCertSet.2.default.name=Validity Default
policyset.auditSigningCertSet.2.default.params.range=720
policyset.auditSigningCertSet.2.default.params.startTime=0
policyset.auditSigningCertSet.3.constraint.class_id=keyConstraintImpl
policyset.auditSigningCertSet.3.constraint.name=Key Constraint
policyset.auditSigningCertSet.3.constraint.params.keyType=-
policyset.auditSigningCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp521
policyset.auditSigningCertSet.3.default.class_id=userKeyDefaultImpl
policyset.auditSigningCertSet.3.default.name=Key Default
policyset.auditSigningCertSet.4.constraint.class_id=noConstraintImpl
policyset.auditSigningCertSet.4.constraint.name=No Constraint
policyset.auditSigningCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl
policyset.auditSigningCertSet.4.default.name=Authority Key Identifier Default
policyset.auditSigningCertSet.5.constraint.class_id=noConstraintImpl
policyset.auditSigningCertSet.5.constraint.name=No Constraint
policyset.auditSigningCertSet.5.default.class_id=authInfoAccessExtDefaultImpl
policyset.auditSigningCertSet.5.default.name=AIA Extension Default
policyset.auditSigningCertSet.5.default.params.authInfoAccessADEnable_0=true
policyset.auditSigningCertSet.5.default.params.authInfoAccessADLocationType_0=URIName
policyset.auditSigningCertSet.5.default.params.authInfoAccessADLocation_0=
policyset.auditSigningCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1
policyset.auditSigningCertSet.5.default.params.authInfoAccessCritical=false
policyset.auditSigningCertSet.5.default.params.authInfoAccessNumADs=1
policyset.auditSigningCertSet.6.constraint.class_id=keyUsageExtConstraintImpl
policyset.auditSigningCertSet.6.constraint.name=Key Usage Extension Constraint
policyset.auditSigningCertSet.6.constraint.params.keyUsageCritical=true
policyset.auditSigningCertSet.6.constraint.params.keyUsageDigitalSignature=true
policyset.auditSigningCertSet.6.constraint.params.keyUsageNonRepudiation=true
policyset.auditSigningCertSet.6.constraint.params.keyUsageDataEncipherment=false
policyset.auditSigningCertSet.6.constraint.params.keyUsageKeyEncipherment=false
policyset.auditSigningCertSet.6.constraint.params.keyUsageKeyAgreement=false
policyset.auditSigningCertSet.6.constraint.params.keyUsageKeyCertSign=false
policyset.auditSigningCertSet.6.constraint.params.keyUsageCrlSign=false
policyset.auditSigningCertSet.6.constraint.params.keyUsageEncipherOnly=false
policyset.auditSigningCertSet.6.constraint.params.keyUsageDecipherOnly=false
policyset.auditSigningCertSet.6.default.class_id=keyUsageExtDefaultImpl
policyset.auditSigningCertSet.6.default.name=Key Usage Default
policyset.auditSigningCertSet.6.default.params.keyUsageCritical=true
policyset.auditSigningCertSet.6.default.params.keyUsageDigitalSignature=true
policyset.auditSigningCertSet.6.default.params.keyUsageNonRepudiation=true
policyset.auditSigningCertSet.6.default.params.keyUsageDataEncipherment=false
policyset.auditSigningCertSet.6.default.params.keyUsageKeyEncipherment=false
policyset.auditSigningCertSet.6.default.params.keyUsageKeyAgreement=false
policyset.auditSigningCertSet.6.default.params.keyUsageKeyCertSign=false
policyset.auditSigningCertSet.6.default.params.keyUsageCrlSign=false
policyset.auditSigningCertSet.6.default.params.keyUsageEncipherOnly=false
policyset.auditSigningCertSet.6.default.params.keyUsageDecipherOnly=false
policyset.auditSigningCertSet.9.constraint.class_id=signingAlgConstraintImpl
policyset.auditSigningCertSet.9.constraint.name=No Constraint
policyset.auditSigningCertSet.9.constraint.params.signingAlgsAllowed=SHA256withRSA,SHA512withRSA,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC,SHA256withRSA/PSS,SHA384withRSA/PSS,SHA512withRSA/PSS
policyset.auditSigningCertSet.9.default.class_id=signingAlgDefaultImpl
policyset.auditSigningCertSet.9.default.name=Signing Alg
policyset.auditSigningCertSet.9.default.params.signingAlg=-
"""

    def __init__(self):
        super(AddProfileCaAuditSigningCert, self).__init__()
        self.message = 'Add caAuditSigningCert profile'

    def upgrade_subsystem(self, instance, subsystem):

        if subsystem.name != 'ca':
            return

        # enable old profile caSignedLogCert to properly deprecate
        opath = os.path.join(subsystem.base_dir, 'profiles', 'ca', 'caSignedLogCert.cfg')
        self.backup(opath)

        oconfig = {}

        pki.util.load_properties(opath, oconfig)

        oconfig['enable'] = 'true'
        oconfig['desc'] = '(deprecated; use caAuditSigningCert) This profile is for enrolling audit log signing certificates'
        oconfig['name'] = '(deprecated; use caAuditSigningCert) Manual Audit Log Signing Certificate Enrollment'

        pki.util.store_properties(opath, oconfig)

        # now handle new profile
        path = os.path.join(subsystem.base_dir, 'profiles', 'ca', 'caAuditSigningCert.cfg')

        if not os.path.exists(path):
            logger.info('Creating caAuditSigningCert.cfg')
            self.backup(path)

            with open(path, 'w') as outfile:
                outfile.write(self.caAuditSigningCert)

            os.chown(path, instance.uid, instance.gid)
            os.chmod(path, 0o0660)

        logger.info('Adding caAuditSigningCert into profile.list')
        profile_list = subsystem.config.get('profile.list').split(',')
        if 'caAuditSigningCert' not in profile_list:
            profile_list.append('caAuditSigningCert')
            profile_list.sort()
            subsystem.config['profile.list'] = ','.join(profile_list)

        logger.info('Adding profile.caAuditSigningCert.class_id')
        subsystem.config['profile.caAuditSigningCert.class_id'] = 'caEnrollImpl'

        logger.info('Adding profile.caAuditSigningCert.config')
        subsystem.config['profile.caAuditSigningCert.config'] = path

        self.backup(subsystem.cs_conf)
        subsystem.save()
