Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 83 Next »


Overview

The goal of this requirement is to implement new micro-service called CertService which will request certificates signed by external Certificate Authority (CA) using CMP over HTTP protocol. Uses CMPv2 client to send and receive CMPv2 messages. 

CertService's client will be also provided so other ONAP components (aka end components) can easily get certificate from CertService. End component is an ONAP component (e.g. DCAE collector or controller) which requires certificate from CMPv2 server to protect external traffic and uses CertService's client to get it.

CertService's client communicates with CertService via REST API over HTTPS, while CertService with CMPv2 server via CMP over HTTP.

To proof that CertService works Open Source CMPv2 server (EJBCA) will be deployed and used in E2E tests.

It is planned that Network Functions (aka xNFs) will get certificates from the same CMPv2 server and the same CA hierarchy, but will use own means to get such certificates. Cause xNFs and ONAP will get certificates signed by the same root CA and will trust such root CA, both parties will automatically trust each other and can communicate with each other.

Architecture sketch

Simplified certificate enrollment flow

Security considerations

CertService's REST API is protected by mutual HTTPS, meaning server requests client's certificate and authenticate only requests with trusted certificate. After ONAP default installation only certificate from CertService's client is trusted. Authorization isn't supported in Frankfurt release.

Components description

CertService

REST API

MethodEndpointParameterReturned values


NameIs required?Transfer methodDescriptionNameAlways returned?Transfer methodDescription
GET

/v1/certificate/{caName}

CA nameYesPath parameterName of Certificate Authority which should sign sent CSR. Must match CertService's CMPv2 servers configuration.Error messageNo, only if error occurred on server sideBody (JSON)Verbose information what wrong happened on server side.
Base64 encoded CSR (Certificate Signing Request) in PEM formatYesHeaderCertificate Signing Request for given componentCertificate chainNo, only in success case.Body (JSON)Base64 encoded (question) signed certificate with whole certificate chain (intermediate CA certificates) in PEM format. Signed certificate should be returned first and then all intermediate certificates in following order: singer of previous certificate till certificate which is signed by root CA. All certificates are in PEM format.
Base64 encoded private key in PEM formatYesHeaderPrivate key. Needed to create proof of possession (PoP)Trusted certificatesNo, only in success case.Body (JSON)Base64 encoded (question) list of trusted certificates in PEM format. In other words list of root CAs which should be treated as trust anchors. Must contain root CA which was used to sign certificate and may contain other root CAs. Order doesn't matter. All certificates are in PEM format. 


Return HTTP codes:

HTTP codeDescription
200 (OK)Everything is ok. Certificate chain and trusted certificates returned
400 (Bad Request)Incorrect/missing CSR and/or private key
401 (Unauthorized)Missing client certificate or presented certificate is not trusted
404 (Not found)Invalid CA name in REST API call or wrong endpoint called
500 (Internal Server Error)In case of exception on server side.



OpenAPI

Swagger will be added here (warning)

CMPv2 server properties

CertService contains configuration of CMPv2 servers. To enroll certificate at least one CMPv2 server has to be configured. CMPv2 servers configuration is read during CertService startup and to take runtime changes into account CertService's refresh configuration endpoint has to be called.

Section holds all properties which are planned to be supported by CertService for CMPv2 based server.


Parameter nameRequiredSyntaxDescriptionValidation rules
CA NameYesString (1-128)The CA name should include the name of the external CA server and the issuerDN, which is the distinguished name of the CA on the external CA server that will sign our certificate.

String (1-128)

URLYesSchema + IPv4/FQDN + port + path

Url to CMPv2 server; includes mandatory parts: scheme (http://) and IPv4/FQDN and optional parts: port and path (alias); e.g. http://127.0.0.1:8080/pkix or http://127.0.0.1/ejbca/publicweb/cmp/cmp


NOTE: If FQDN is given ONAP must be able to resolve it without extra manual configuration

Must be correct URL

Must start with http:// scheme

If port given, port from 1-65535 range

Issuer DNYesString (4-256)Distinguished Name of the CA that will sign the certificate on the CMPv2 server side. When creating an end entity on the external CA server for client mode this IssuerDN will be passed through as the ca to sign for that user.

String (4-256)

Correct DN

CA ModeYesEnum (CLIENT|RA)Issuer mode (either Registration Authority (RA) or client mode)

Value from predefined set

Authentication data::IAKYesString (1-256)Initial authentication key, used, together with RV, to authenticate request in CMPv2 server

String (1-256)

Authentication data::RVYesString (1-256)Reference value, used, together with IAK, to authenticate request in CMPv2 server

String (1-256)


Example

# WARNING - work in progress so still can change
{
   "cmpv2Servers":[
      {
         "caName":"TEST",
         "url":"http://127.0.0.1/ejbca/publicweb/cmp/cmp",
         "issuerDN":"CN=ManagementCA",
         "caMode":"CLIENT",
         "authentication":{
            "iak":"xxx",
            "rv":"yyy"
         }
      },
      {
         "caName":"TEST2",
         "url":"http://127.0.0.1/ejbca/publicweb/cmp/cmpRA",
         "issuerDN":"CN=ManagementCA2",
         "caMode":"RA",
         "authentication":{
            "iak":"xxx",
            "rv":"yyy"
         }
      }
   ]
}

CMPv2 client

Input table for CMPv2 client

CMPv2 will get two POJOs and one String: first with CSR, plain fields extracted from CSR (like subject DN, list of SANs, etc) and private key (in general data passed via REST API call) and second with CMPv2 server details and CA name


Input valueInput typeDescriptionUsage
CsrModelObjectPOJO which transfers sent CSR, plain fields extracted from CSR (like Common Name, Country, etc)
CsrModel:: csrorg.bouncycastle.pkcs.PKCS10CertificationRequest (question)Certificate Signing Request received via REST API
CsrModel:: subjectDNorg.bouncycastle.asn1.x500.X500NameSubjectDN retrieved from sent CSR
CsrModel:: privateKeyjava.security.PrivateKeyPrivate key received via REST API
CsrModel:: publicKeyjava.security.PublicKeyPublic key retrieved from sent CSR
CsrModel:: sansList of StringsSubject Alterative Names retrieved from sent CSR
CsrModel:: (question)(question)(question)(warning) Others (plain data extracted from sent CSR)  if needed (warning)(question)(question)(question)
CMPv2ServerDetailsObjectPOJO which transfers CMPv2 server properties
CMPv2ServerDetails:: CA nameStringCA name as configured in CMPv2 server properties
CMPv2ServerDetails:: URLURL or StringURL to CMPv2 server as configured in CMPv2 server details
CMPv2ServerDetails:: IssuerDNorg.bouncycastle.asn1.x500.X500NameIssuer DN as configured in CMPv2 server details
CMPv2ServerDetails:: CA modeENUMCA mode as configured in CMPv2 server details
CMPv2ServerDetails:: IAKStringIAK as configured in CMPv2 server details
CMPv2ServerDetails:: RVStringRV as configured in CMPv2 server details
CA nameStringCA name received via REST API


Return values from CMPv2 client

CMPv2 client returns:

List <java.security.cert.X509Certificate> certificateChain

List <java.security.cert.X509Certificate> trustedCerts

CMPv2 client POC

TBD (warning)

Currently the POC for CMPv2 client is working based on the inputs below.

Input Values

Input Type

Description

Usage

csrMetaobjectcsrMeta object from aaf, would contain values needed for certificate request. any needed values that should be stored in the csrMeta will be mentioned below.stores all pertinent values for certificate request - these will be detailed below, and should be set before being passed to the cmpv2 client.
csrMeta:IssuerDnorg.bouncycastle.asn1.x500.X500Namedistinguished name of the CA we're receiving certificate from. Cannot be nullused in the creation of the cert on EJBCA server
csrMeta: SubjectDnorg.bouncycastle.asn1.x500.X500NameDistinguished name of the Entity the certificate is being issued to/ Certificate Requesting Entity. Cannot be null.used in the creation of the cert on EJBCA server
csrMeta: KeyPairjava.security.KeyPairKeyPair associated with the entity the certificate is being issued to. Cannot be nullused to create proof of possession for request to EJBCA server
csrMeta: Passwordobject which contains iak/rv?secret password value shared by EJBCA server. Cannot be nullused to authenticate ourselves to the EJBCA serve

csrMeta: CA Details

objectCertification Authority Details ( Http address, Port number and Path (which includes alias if used)). Cannot be nullused to Post Http request to External CA.

.cer file

java.security.cert.X509Certificate.cer (CSR) generated by Cert-man using Key-pair. Cannot be null.

used to validate response (.crt)/ certificate send from EJBCA server

caNamestringthe name which is a general description of the external CAused for debugging purposes
caModeenumstring noting whether the server we are contacting will be operating in either client or RA modeused for debugging purposes


Relevant values in Certificate Request message to EJBCA:

Value

Description

Information Included

PKIHeaderContains information common to many PKI messages.

SenderDN

IssuerDN

ProtectionAlgorithm (used for PkiProtection below)

PKIBodycontains message-specific information ie. certificate request message

CertificateRequestMessage, which includes:

SubjectDN

IssuerDN

SubjectPublicKey

PKIProtectioncontains bits that protect PKImessage (Specifically the iak/rv)



Test code for running cmpv2 client against EJBCA server through unit test

@Test
  public void testServerWithRealUrl() throws CmpClientException {

    setValidCsrMetaValuesAndDateValues();

    csrMeta.caUrl("http://127.0.0.1/ejbca/publicweb/cmp/cmpRA");
    csrMeta.password("mypassword");

    CmpClientImpl cmpClient = new CmpClientImpl(HttpClients.createDefault());
    cmpClient.createCertificate("data", "RA", csrMeta, cert, notBefore, notAfter);
  }

  private void setValidCsrMetaValuesAndDateValues() {
    ArrayList<RDN> rdns = new ArrayList<>();
    try {
      rdns.add(new RDN("O=CommonCompany"));
    } catch (CertException e) {
      e.printStackTrace();
    }
    csrMeta = new CSRMeta(rdns);
    csrMeta.cn("CN=CommonName");
    csrMeta.san("CommonName.com");
    csrMeta.password("password");
    csrMeta.email("CommonName@cn.com");
    csrMeta.issuerCn("CN=ManagementCA");
    when(kpg.generateKeyPair()).thenReturn(keyPair);
    csrMeta.keypair();
    csrMeta.caUrl("http://127.0.0.1/ejbca/publicweb/cmp/cmp");

    try {
      notBefore =
              new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
      notAfter =
              new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
    } catch (ParseException e) {
      e.printStackTrace();
    }
  }


Usage

Docker

Run CertService as docker via following command: (warning) TBA (warning)

docker run -p 8080:8080 --name cert-service $IMAGE_NAME


Kubernetes

For Kubernetes helm chart is provided. Just overwrite needed values and deploy helm chart using following command: (warning) TBA (warning)

helm install --name $NAME --namespace onap $PATH_TO_HELM_CHART --values $PATH_TO_OVERRIDDEN_VALUES


CertService's client

CertService's client input properties

GroupParameter nameENV variable nameRequiredDefaultSyntaxValidation rulesDescriptionOrigin

UrlREQUEST_URLNohttp(s)://aaf-cert-service-service:8080/v1/certificate/URLSyntax column

URL to Cert Service. Default value will be aligned with ONAP K8s deployment (Cert Service's K8s service name and port). Needs to be changed for plain docker deployment.

Application helm chart

TimeoutREQUEST_TIMEOUTNo30000

Int (0-120000)

Syntax columnTimeout for REST API calls. In miliseconds. A timeout value of zero is interpreted as an infinite timeout.Application helm chart

PathOUTPUT_PATHYes
String (1-256)

Syntax column

Path is valid *inx path

Path where client will output generated keystore and truststore. Normally this path should be on a volume which is used to transfer keystore and truststore between CertService's client and end componentApplication helm chart

CA nameCA_NAMEYes
String (1-128)

Syntax column

Must contain only alphanumeric characters

Name of CA which will enroll certificate. Must be same as configured on server side. Used in REST API callsOOM global value





CSR details

Common NameCOMMON_NAMEYes
String (1-256)

Syntax column

CN can't contain (special characters (?, $, % and so on), IP addresses, Port numbers, or "http:// or https://")

Common name for which certificate from CMPv2 server should be issuedApplication helm chart
OrganizationORGANIZATIONYes
String (1-256)

Syntax column

Organization can't contain invalid characters from list "! @ # $ % ^ * ( ) ~ ? > < / \" (without "")

Organization for which certificate from CMPv2 server should be issuedOOM global value
Organization UnitORGANIZATION_UNITNoNot available in generated certificateString (0-256)Syntax columnOrganization unit for which certificate from CMPv2 server should be issuedOOM global value
LocationLOCATIONNoNot available in generated certificateString (0-256)

Syntax column


Location for which certificate from CMPv2 server should be issuedOOM global value
StateSTATEYes
String (1-256)Syntax columnState for which certificate from CMPv2 server should be issuedOOM global value
CountryCOUNTRYYes
String(2)C must be a 2-character ISO format country codeCountry for which certificate from CMPv2 server should be issuedOOM global value
SANsSANSNoNot available in generated certificate

String (0-2048)

SAN1[:SAN2]

Syntax columnSubject Alternative Names (SANs) for which certificate from CMPv2 server should be issued. Colon is used as delimiter, e.g. example.com:example.pl. The only supported type of SANs is DNS domain name.Application helm chart

Results

As the successful result of running CertService's client (exitCode = 0) following artifacts are created:


NameDescription
keystore.jksKeystore with certificate chain saved under 'certificate' alias. Protected by random generated password.
keystore.passFile with password to keystore. Password should be min. 16 chars long and should contain only alphanumeric characters and special characters like Underscore (_), Dollar ($) and Pound (#). Password should be random.
truststore.jksTruststore with all trusted certificates. Protected by random generated password. Every trusted certificate is saved under alias with 'trusted-certificate-' prefix.
truststore.passFile with password to truststore. Password should be min. 16 chars long and should contain only alphanumeric characters and special characters like Underscore (_), Dollar ($) and Pound (#). Password should be random.


In case of error CertService's client returns other exit codes (errorCode != 0). 

Usage

Docker

Run CertService's client as docker via following command: (warning) TBA (warning)

 


Kuberenetes

Cause ONAP is deployed in K8s, CertService's client will be delivered as independent container and should run as init container for end component. Both init container and end component must mount the same volume (persistent or ephemeral) to transfer generated artifacts.

Example

Volume to transfer generated artifacts should be mounted to application container (lines 46-49). Within K8s workload, CertService's client as init container should be added (lines 10-13). All needed ENV variables should be passed to CertService's client (lines 14-36). CertService's client should mount the same volume as application container (lines 37-39). Volume to transfer generated artifacts can be an emptyDir type (lines 51-53).

...                                 # WARNING - work in progress so still can change
kind: Deployment
metadata:
  ...
spec:
...
  template:
  ...
    spec:
      initContainers:
        - name: cert-service-client
          image: {{ .Values.global.csClientRepository }}/{{ .Values.global.csClientImage }}
          imagePullPolicy: {{ .Values.global.pullPolicy | default .Values.pullPolicy }}
          env:
            - name: REQUEST_URL
              value: {{ .Values.certService.url }}
            - name: REQUEST_TIMEOUT
              value: {{ .Values.certService.timeout }}
            - name: OUTPUT_PATH
              value: {{ .Values.certService.outputPath }}
            - name: CA_NAME
              value: {{ .Values.global.certService.caName }}
            - name: COMMON_NAME
              value: {{ .Values.certService.commonName }}
            - name: ORGANIZATION
              value: {{ .Values.global.certService.organization }}
            - name: ORGANIZATION_UNIT
              value: {{ .Values.global.certService.organizationUnit }}
            - name: LOCATION
              value: {{ .Values.global.certService.location }}
            - name: STATE
              value: {{ .Values.global.certService.state }}
            - name: COUNTRY
              value: {{ .Values.global.certService.country }}
            - name: SANS
              value: {{ .Values.certService.sans }}
          volumeMounts:
            - mountPath: {{ .Values.certService.outputPath }}
              name: {{ include "common.fullname" . }}-cmpv2-certs
      containers:
        - name: {{ include "common.name" . }}
          image: "{{ include "common.repository" . }}/{{ .Values.image }}"
          imagePullPolicy: {{ .Values.global.pullPolicy | default .Values.pullPolicy }}
          resources:
{{ include "common.resources" . | indent 12 }}
          volumeMounts:
            - mountPath: /certificates/external
              name: {{ include "common.fullname" . }}-cmpv2-certs
              readOnly: true
          ...
      volumes:
        - name: {{ include "common.fullname" . }}-cmpv2-certs
          emptyDir: {}

CMPv2 server

For testing purpose EJBCA is set up. It is configured with 2 layer CA hierarchy (root CA and intermediate CA).

EJBCA Setup Script


  • No labels