Skip to content
This repository has been archived by the owner on Nov 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #64 from EVOLVED-5G/CAPIF_aef_demo
Browse files Browse the repository at this point in the history
Capif aef demo
  • Loading branch information
alemosan1 authored Oct 3, 2022
2 parents 25685f5 + 8f381c5 commit edf9249
Show file tree
Hide file tree
Showing 31 changed files with 602 additions and 231 deletions.
6 changes: 3 additions & 3 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
cff-version: 2.0.0
cff-version: 2.1.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "EVOLVED-5g"
given-names: "EVOLVED-5g"
title: "CAPIF_API_Services"
version: 2.0
date-released: 2022-09-23
version: 2.1
date-released: 2022-01-30
url: "https://github.com/EVOLVED-5G/CAPIF_API_Services"
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- [Mongo DB Dashboard](#mongo-db-dashboard)
- [CAPIF Tool Release 1.0](#capif-tool-release-10)
- [CAPIF Tool Release 2.0](#capif-tool-release-20)
- [CAPIF Tool Release 2.1](#capif-tool-release-21)


# Repository structure
Expand Down Expand Up @@ -552,4 +553,30 @@ Additional information about this version:
- JWT Authentication Server
- Easy RSA Server
- TLS Enabled
hola


# CAPIF Tool Release 2.1

This CAPIF services have many stability improvements:
- API Provider Management Service adds TLS connection using certificates.
- Added logs on Services.
- Easy RSA:
- Fix: recreate always when we try to sign a public key. Previously if there are a signed key with same filename causes a MISMATCH error.
- Code refactor.
- Scripts added for manual remove of signed certificates.
- JWT Auth Service:
- code refactor
- New register operation added, distinguish between invoker and exposer logic.
- NGINX service:
- Adjusted rounting information.
- TLS over API Provider Management Service.
- removed not used endpoints
- TLS over some endpoint at JWT Auth Service.
- Added retry to obtain ca root certificate over Easy RSA service.
- Added check of ca.crt obtained.
- nginx_prepare.sh is refactored and parametrized.
- Robot Framework Test:
- Adjusted the register flow for exposer and invoker.
- End points used in that flow are changed.
- API Provider Management tests adapted to use TLS.

15 changes: 15 additions & 0 deletions pac/Jenkins-dummy.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
pipeline {
agent any

parameters {
string(name: 'GIT_CICD_BRANCH', defaultValue: 'develop', description: 'Deployment git branch name')
}

stages {
stage('Say Hello and Goobye!') {
steps {
echo "Hello and Goodbye"
}
}
}
}
2 changes: 2 additions & 0 deletions pac/Jenkinsfile-capif-tests.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pipeline {
disableConcurrentBuilds()
buildDiscarder(logRotator(daysToKeepStr: '14', numToKeepStr: '30', artifactDaysToKeepStr: '14', artifactNumToKeepStr: '30'))
ansiColor('xterm')
timeout(time: 15, unit: 'MINUTES')
retry(2)
}
parameters {
string(name: 'BRANCH_NAME', defaultValue: 'develop', description: 'Deployment git branch name')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import connexion
import six
import json

from flask import Response, request
from ..core.provider_enrolment_details_api import ProviderManagementOperations
from ..core.check_user import CapifUsersOperations
from ..encoder import JSONEncoder
from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501
from api_provider_management.models.problem_details import ProblemDetails # noqa: E501
from api_provider_management import util
from cryptography.hazmat.backends import default_backend
from cryptography import x509


provider_management_ops = ProviderManagementOperations()
check_user = CapifUsersOperations()

def registrations_post(body): # noqa: E501
"""registrations_post
Expand All @@ -20,6 +27,20 @@ def registrations_post(body): # noqa: E501
:rtype: APIProviderEnrolmentDetails
"""

cert_tmp = request.headers['X-Ssl-Client-Cert']
cert_raw = cert_tmp.replace('\t', '')


cert = x509.load_pem_x509_certificate(str.encode(cert_raw), default_backend())
cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value.strip()

capif_user = check_user.check_capif_user(cn, "exposer")

if not capif_user:
prob = ProblemDetails(title="Unauthorized", status=401, detail="User not authorized",
cause="Certificate not authorized")
return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype='application/json')


if connexion.request.is_json:
body = APIProviderEnrolmentDetails.from_dict(connexion.request.get_json()) # noqa: E501
Expand All @@ -40,6 +61,20 @@ def registrations_registration_id_delete(registration_id): # noqa: E501
:rtype: None
"""
cert_tmp = request.headers['X-Ssl-Client-Cert']
cert_raw = cert_tmp.replace('\t', '')


cert = x509.load_pem_x509_certificate(str.encode(cert_raw), default_backend())
cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value.strip()

capif_user = check_user.check_capif_user(cn, "exposer")

if not capif_user:
prob = ProblemDetails(title="Unauthorized", status=401, detail="User not authorized",
cause="Certificate not authorized")
return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype='application/json')

res = provider_management_ops.delete_api_provider_enrolment_details(registration_id)

return res
Expand All @@ -57,9 +92,23 @@ def registrations_registration_id_put(registration_id, body): # noqa: E501
:rtype: APIProviderEnrolmentDetails
"""
cert_tmp = request.headers['X-Ssl-Client-Cert']
cert_raw = cert_tmp.replace('\t', '')


cert = x509.load_pem_x509_certificate(str.encode(cert_raw), default_backend())
cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value.strip()

capif_user = check_user.check_capif_user(cn, "exposer")

if not capif_user:
prob = ProblemDetails(title="Unauthorized", status=401, detail="User not authorized",
cause="Certificate not authorized")
return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype='application/json')

if connexion.request.is_json:
body = APIProviderEnrolmentDetails.from_dict(connexion.request.get_json()) # noqa: E501

res = provider_management_ops.update_api_provider_enrolment_details(registration_id,body)

return res
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
from email.quoprimime import body_decode
import connexion
import six
import json

from flask import Response, request
from ..core.provider_enrolment_details_api import ProviderManagementOperations
from ..core.check_user import CapifUsersOperations
from ..encoder import JSONEncoder
from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501
from api_provider_management.models.api_provider_enrolment_details_patch import APIProviderEnrolmentDetailsPatch # noqa: E501
from api_provider_management.models.problem_details import ProblemDetails # noqa: E501
from api_provider_management import util
from cryptography.hazmat.backends import default_backend
from cryptography import x509

check_user = CapifUsersOperations()
provider_management_ops = ProviderManagementOperations()


Expand All @@ -23,6 +30,20 @@ def modify_ind_api_provider_enrolment(registration_id, body): # noqa: E501
:rtype: APIProviderEnrolmentDetails
"""
cert_tmp = request.headers['X-Ssl-Client-Cert']
cert_raw = cert_tmp.replace('\t', '')


cert = x509.load_pem_x509_certificate(str.encode(cert_raw), default_backend())
cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value.strip()

capif_user = check_user.check_capif_user(cn, "exposer")

if not capif_user:
prob = ProblemDetails(title="Unauthorized", status=401, detail="User not authorized",
cause="Certificate not authorized")
return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype='application/json')

if connexion.request.is_json:
body = APIProviderEnrolmentDetailsPatch.from_dict(connexion.request.get_json()) # noqa: E501

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import sys
from ..db.db import MongoDatabse

class CapifUsersOperations:

def __init__(self):
self.db = MongoDatabse()

def check_capif_user(self, common_name, role):
try:
mycol = self.db.get_col_by_name(self.db.capif_users)

capif_user = mycol.find_one({"$and": [{"cn": common_name}, {"role": role}]})

if capif_user is None:
return False

return True
except Exception as e:
print("An exception occurred ::", e, file=sys.stderr)
return False
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def __init__(self):
self.config = Config().getConfig()
self.db = self.__connect()
self.provider_enrolment_details = self.config['mongo']['col']
self.capif_users = self.config['mongo']['capif_users']

def get_col_by_name(self, name):
return self.db[name]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mongo: {
'password': 'example',
'db': 'capif',
'col': 'providerenrolmentdetails',
'jwt': 'user',
'capif_users': 'user',
'host': 'mongo',
'port': "27017"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ swagger-ui-bundle >= 0.0.2
python_dateutil >= 2.6.0
setuptools >= 21.0.0
Flask == 2.0.3
cryptography
pymongo == 4.0.1
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def subscriber_id_subscriptions_post(subscriber_id, body): # noqa: E501
cert = x509.load_pem_x509_certificate(str.encode(cert_raw), default_backend())
cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value.strip()

capif_user = check_user.check_capif_user(cn, "invoker", "apf")
capif_user = check_user.check_capif_user(cn, "invoker", "exposer")

if not capif_user:
prob = ProblemDetails(title="Unauthorized", status=401, detail="User not authorized",
Expand Down
1 change: 1 addition & 0 deletions services/easy_rsa/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ COPY requirements.txt requirements.txt
RUN pip3 install --no-cache-dir -r requirements.txt

COPY . .
RUN chmod a+x *.sh

EXPOSE 8080

Expand Down
32 changes: 25 additions & 7 deletions services/easy_rsa/app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

from flask import Flask, jsonify, request, Response
from typing import List
from flask import Flask, jsonify, request, Response, current_app
import json
import subprocess
import sys
Expand Down Expand Up @@ -31,6 +32,12 @@ def sign_csr():
mode = request.json["mode"]
filename = request.json["filename"]

app.logger.info("sign-csr for user "+ filename)
names = get_files(filename)

if len(names) != 0:
revoke_list(names)

csr_file = open(filename + '.csr', 'wb')
csr_file.write(bytes(csr, 'utf-8'))
csr_file.close()
Expand All @@ -56,11 +63,15 @@ def sign_csr():

@app.route("/certdata", methods=["DELETE"])
def data_test():
names = get_files('ROBOT_TESTING')

return revoke_list(names)

def get_files(prefix):
files = []
dir_list = os.listdir()
for file in dir_list:
if file.startswith('ROBOT_TESTING'):
if file.startswith(prefix):
files.append(file)

print(files)
Expand All @@ -72,13 +83,20 @@ def data_test():
convert_list_to_set = set(names)
names = list(convert_list_to_set)
print("Entities to remove", names)
return names

def revoke_cert(name):
p = subprocess.call("/root/EasyRSA-3.0.4/easyrsa --batch revoke {}".format(name),
stdout=subprocess.PIPE, shell=True)
delete_file('/root/{}.csr'.format(name))
delete_file('/root/pki/issued/{}.crt'.format(name))
delete_file('/root/pki/reqs/{}.req'.format(name))
current_app.logger.info("cert %s removed", name)


def revoke_list(names=list):
for name in names:
p = subprocess.call("/root/EasyRSA-3.0.4/easyrsa --batch revoke {}".format(name),
stdout=subprocess.PIPE, shell=True)
delete_file('/root/{}.csr'.format(name))
delete_file('/root/pki/issued/{}.crt'.format(name))
delete_file('/root/pki/reqs/{}.req'.format(name))
revoke_cert(name)

res = Response(json.dumps({'certificate_removed': names}),
status=200, mimetype='application/json')
Expand Down
5 changes: 5 additions & 0 deletions services/easy_rsa/revoke_demo_users.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash
DUMMY=dummy
CUSTOMER_EXPOSER=customexposer
./revoke_user.sh $DUMMY
./revoke_user.sh $CUSTOMER_EXPOSER
10 changes: 10 additions & 0 deletions services/easy_rsa/revoke_user.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
USER=dummy
if [ "$#" -eq 1 ]; then
USER=$1
fi

/root/EasyRSA-3.0.4/easyrsa --batch revoke $USER
rm -rf /root/$USER.csr
rm -rf /root/pki/issued/$USER.crt
rm -rf /root/pki/reqs/$USER.req
3 changes: 2 additions & 1 deletion services/jwt_auth/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ WORKDIR /usr/src/app

COPY requirements.txt /usr/src/app/requirements.txt

RUN apk add -U --no-cache gcc build-base linux-headers ca-certificates libffi-dev libressl-dev libxslt-dev
RUN pip3 install --no-cache-dir -r requirements.txt

COPY . /usr/src/app
Expand All @@ -13,4 +14,4 @@ EXPOSE 8080

ENTRYPOINT ["python3"]

CMD ["-m", "app"]
CMD ["-m", "register_service"]
Loading

0 comments on commit edf9249

Please sign in to comment.