diff options
author | Brinda Santh <bs2796@att.com> | 2019-10-22 20:47:12 -0400 |
---|---|---|
committer | Brinda Santh <bs2796@att.com> | 2019-10-22 20:47:12 -0400 |
commit | a5ceb2485df10aa4987c64975d7200ff090c5890 (patch) | |
tree | 15b22424eccfd78996d717873a6a1517e2820a4e /ms/py-executor | |
parent | 910fa69e65b3d151ef2bdbbf90fdcc31cfa01008 (diff) |
Py executor grpc TLS server authentication.
Issue-ID: CCSDK-1854
Signed-off-by: Brinda Santh <bs2796@att.com>
Change-Id: I72b3deb7976e7d3e44478c497a46b9b4ac428623
Diffstat (limited to 'ms/py-executor')
-rw-r--r-- | ms/py-executor/README | 5 | ||||
-rw-r--r-- | ms/py-executor/client.py | 67 | ||||
-rw-r--r-- | ms/py-executor/configuration.ini | 7 | ||||
-rwxr-xr-x | ms/py-executor/dc/docker-compose.yaml | 6 | ||||
-rwxr-xr-x | ms/py-executor/docker/distribution.xml | 3 | ||||
-rw-r--r-- | ms/py-executor/py-executor-chain.pem | 27 | ||||
-rw-r--r-- | ms/py-executor/py-executor-key.pem | 52 | ||||
-rw-r--r-- | ms/py-executor/server.py | 44 |
8 files changed, 199 insertions, 12 deletions
diff --git a/ms/py-executor/README b/ms/py-executor/README new file mode 100644 index 000000000..919795a3c --- /dev/null +++ b/ms/py-executor/README @@ -0,0 +1,5 @@ + +Generate Server Certificates +------------------------------ + +openssl req -x509 -newkey rsa:4096 -keyout py-executor-key.pem -out py-executor-chain.pem -days 3650 -nodes -subj '/CN=localhost'
\ No newline at end of file diff --git a/ms/py-executor/client.py b/ms/py-executor/client.py new file mode 100644 index 000000000..c5bdc43c8 --- /dev/null +++ b/ms/py-executor/client.py @@ -0,0 +1,67 @@ +# Copyright © 2018-2019 AT&T Intellectual Property. +# +# 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. +# +# 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 grpc +from blueprints_grpc.proto.BluePrintProcessing_pb2_grpc import BluePrintProcessingServiceStub +from blueprints_grpc.proto.BluePrintProcessing_pb2 import ExecutionServiceInput +from blueprints_grpc.proto.BluePrintCommon_pb2 import CommonHeader, ActionIdentifiers + + +def generate_messages(): + commonHeader = CommonHeader() + commonHeader.requestId = "1234" + commonHeader.subRequestId = "1234-1" + commonHeader.originatorId = "CDS" + + actionIdentifiers = ActionIdentifiers() + actionIdentifiers.blueprintName = "sample-cba" + actionIdentifiers.blueprintVersion = "1.0.0" + actionIdentifiers.actionName = "SampleScript" + + input = ExecutionServiceInput(commonHeader=commonHeader, actionIdentifiers=actionIdentifiers) + + commonHeader2 = CommonHeader() + commonHeader2.requestId = "1235" + commonHeader2.subRequestId = "1234-2" + commonHeader2.originatorId = "CDS" + input2 = ExecutionServiceInput(commonHeader=commonHeader2, actionIdentifiers=actionIdentifiers) + + inputs = [input, input2] + for input in inputs: + print(input) + yield input + + +if __name__ == '__main__': + with open('py-executor-chain.pem', 'rb') as f: + creds = grpc.ssl_channel_credentials(f.read()) + channel = grpc.secure_channel('localhost:50052', creds) + stub = BluePrintProcessingServiceStub(channel) + + messages = generate_messages() + responses = stub.process(messages) + for response in responses: + print(response) diff --git a/ms/py-executor/configuration.ini b/ms/py-executor/configuration.ini index 8c36dd04f..5688f39bd 100644 --- a/ms/py-executor/configuration.ini +++ b/ms/py-executor/configuration.ini @@ -1,6 +1,11 @@ [scriptExecutor] port=%(APP_PORT)s -auth=%(BASIC_AUTH)s +authType=%(AUTH_TYPE)s +# For Token Auth +token=%(AUTH_TOKEN)s +# For TLS Auth +certChain=%(AUTH_CERT_CHAIN)s +privateKey=%(AUTH_PRIVATE_KEY)s logFile=%(LOG_FILE)s maxWorkers=20 diff --git a/ms/py-executor/dc/docker-compose.yaml b/ms/py-executor/dc/docker-compose.yaml index 76009411b..30298e3c0 100755 --- a/ms/py-executor/dc/docker-compose.yaml +++ b/ms/py-executor/dc/docker-compose.yaml @@ -16,7 +16,11 @@ services: STICKYSELECTORKEY: ENVCONTEXT: dev APP_PORT: 50052 - BASIC_AUTH: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw== + #AUTH_TYPE: basic-auth + #AUTH_TOKEN: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw== + AUTH_TYPE: tls-auth + AUTH_CERT_CHAIN: /opt/app/onap/python/py-executor-chain.pem + AUTH_PRIVATE_KEY: /opt/app/onap/python/py-executor-key.pem LOG_FILE: /opt/app/onap/logs/application.log volumes: diff --git a/ms/py-executor/docker/distribution.xml b/ms/py-executor/docker/distribution.xml index 6235a7b8a..bb7a8d20a 100755 --- a/ms/py-executor/docker/distribution.xml +++ b/ms/py-executor/docker/distribution.xml @@ -38,6 +38,9 @@ <includes> <include>requirements.txt</include> <include>configuration.ini</include> + <include>*.crt</include> + <include>*.key</include> + <include>*.pem</include> </includes> <useDefaultExcludes>true</useDefaultExcludes> <fileMode>0666</fileMode> diff --git a/ms/py-executor/py-executor-chain.pem b/ms/py-executor/py-executor-chain.pem new file mode 100644 index 000000000..30f09dfea --- /dev/null +++ b/ms/py-executor/py-executor-chain.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEpDCCAowCCQDyhR+GR2RUiTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls +b2NhbGhvc3QwHhcNMTkxMDIzMDAwMTA0WhcNMjkxMDIwMDAwMTA0WjAUMRIwEAYD +VQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCs +c4d6qfbW+GSMp+XURoLXtSAbbehoBXL2beSzqQNW6e+Q9IVtSPZst8VRjUXelFzM +m7VpS9jhiXOPZ5KKUOD0GVuNQc54VpwtHt7t9L5wS9OvdnLijnMIkc0iUvC6+Rcq +HSfbNC2Tb+a8jLwojmtRCeY/MyCnmqYpD+U3b6Eue89VpMOIfmDuTqSRRBYNVO72 +hq7FI3UD8+zREg7htfzjJjG14Ec5iVMDxJA1FlwtXFnZxDHgbLjEVjTTR/9Wm1eU +aJ4oWRt3gG/vnJNa+GwN4w/My+j/5/n/YpNh6GeQrHxBl/SL/SAFBshlwozr4K4K +av5MqRKyhCACV4SsdhKJUEDtvrtukJvh/ZDW8jdNbFJAljm8UucZGbJrZl6G7XB3 +WteI7rezo0mL0NMBZIT3nQSMEpefKUFZFiE5lYvIk3UuChqIM0xdgV4INwLRHZdc +1TtiGaBJV05y3Klo5gaUgNGbHP26zfub5TydiMrOA5W2mUvMkG2oit9aqnbaZBLD +t17cCKzpzcVF5uNUng3j6sQvpTt3S4L28TvKUMAfpecQqvxMoxG0/9HZuv2z+U+L +LVVsS07yJPIGMLcq1LMM++8LwD1MupcoShjNOq/lUOL6hIMfLOIfxt8Kv8WykVzv +6yjKEIurjkwMipq4kvr9J7FFi54kGr7uvXWQRHDFJwIDAQABMA0GCSqGSIb3DQEB +CwUAA4ICAQB7gJzvaOIP3/S2jrObz67g0jiz1cfb4I9KQwpwb6JUWbYm1QjBcGm4 +IhNbdPMD6dpwBc/A4JctA5E+/fArvl14UtK1jkaaE/GCumL0VUSZeAM6CK/63brt +LplqCunv8ePHmiwjJBnhu+ewe1+mDMVDMw0iot/q+pOM3vqNS1Fipja+xFK1JQZx +JmkjW/Ug3NHk/SSTfO+VNmlI5bBBApMqKmd9picsyDZ7dTBtZvbqV5eQsPZvv14G +oEvWnvvom+D5GojroSO+OMHNDR3bzK6p0Cu8AiTy9Ls6J2e4GXJz3Cg/kuF9tNlR +3X62zDT+CUipuYyTvmjbSyNMGwU7BIZTKFPuTtjh7EwT2g6S8RV9PmT98CQW6kTT +RJbL7nMIOF0WusysAT5wj1HJ0QKBQCXK+L6WTKTTovaEE7JSVrYe7wVF8Q9SyBIM +4CPVZt+GMyQKJ9SRnVgTDEMb7sj9HPaoVeDc6LQTv8Q//wFeTdZIWXQhpVJCQCEG +qkRk9r3isF60ISOXXIYhqE+hx3QXY9M2UyHDtKXPZ7X370vADi2ebBMF8MpIZYl5 +628dME9JhOhLhD5qPJeva2Nq4gLpK+rO6t7ML0Us4edoKyoScowXAh80q1GW3EO3 +IxTK123651C/S0kDqLqZ9rknEdpwSujrT2UW95jUlfo5OKDrPpdOBw== +-----END CERTIFICATE----- diff --git a/ms/py-executor/py-executor-key.pem b/ms/py-executor/py-executor-key.pem new file mode 100644 index 000000000..830a3ae21 --- /dev/null +++ b/ms/py-executor/py-executor-key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCsc4d6qfbW+GSM +p+XURoLXtSAbbehoBXL2beSzqQNW6e+Q9IVtSPZst8VRjUXelFzMm7VpS9jhiXOP +Z5KKUOD0GVuNQc54VpwtHt7t9L5wS9OvdnLijnMIkc0iUvC6+RcqHSfbNC2Tb+a8 +jLwojmtRCeY/MyCnmqYpD+U3b6Eue89VpMOIfmDuTqSRRBYNVO72hq7FI3UD8+zR +Eg7htfzjJjG14Ec5iVMDxJA1FlwtXFnZxDHgbLjEVjTTR/9Wm1eUaJ4oWRt3gG/v +nJNa+GwN4w/My+j/5/n/YpNh6GeQrHxBl/SL/SAFBshlwozr4K4Kav5MqRKyhCAC +V4SsdhKJUEDtvrtukJvh/ZDW8jdNbFJAljm8UucZGbJrZl6G7XB3WteI7rezo0mL +0NMBZIT3nQSMEpefKUFZFiE5lYvIk3UuChqIM0xdgV4INwLRHZdc1TtiGaBJV05y +3Klo5gaUgNGbHP26zfub5TydiMrOA5W2mUvMkG2oit9aqnbaZBLDt17cCKzpzcVF +5uNUng3j6sQvpTt3S4L28TvKUMAfpecQqvxMoxG0/9HZuv2z+U+LLVVsS07yJPIG +MLcq1LMM++8LwD1MupcoShjNOq/lUOL6hIMfLOIfxt8Kv8WykVzv6yjKEIurjkwM +ipq4kvr9J7FFi54kGr7uvXWQRHDFJwIDAQABAoICADepPmRAMbTnDYU8t/jRHXBE +PO29htL0V0vk4nl+pt5JuZJe6iYA89DZa+3LnG6gEmfUJjSrT4BUXiE+O9U7D7CZ +8qvgPqUmx1fk6+2AHmuefd/XanNnqQduD/jxLlQbC/gC2xdsev1ok9/tyNmKRmcs +u81QUkzmpJUCVWiUNkELozswaBBJQj4I0iM1B60b6dlWVVi5/g3dkGVW38jIdaxX +apoansKaaVoA+s63vd7CPRoFsleOoAB3FqvPREIO97CmJ848HJpwsTB0qDcnkbDV +xgbDFhxrIozko09ptOvEUILXag45EDmvG8WEivmjVml0aUoTFD7cWHyJBQCpR4fU +5W9mYd4Rrzbmpb+LGYdNyrp3wo3C7dJ7/ffBMQxmXTdMZkcxorxj4BRG3oACRQ1u +Ff1iUruZzIIDtEkrC9hc5QpLlDf9b1obm8L9sxf1QmTt59o5oFG40GPwPP19GXwE +l2faHwho2jYLM9rhuSsK/5sSmUshPNQYmfMnbWzTtghMPE/g0Cfpt8qbspq+G1bk +z3M97JlFMF83ccRotDElX9E/ttjU7Lehoz+1sOyHiVW1E4oqKer4t+nI2bp6VYZm +W94qptW7kb4o0DsvPCaoTPBxLJ1ag2WBlqoFkVI0YaxZiZ8OTR55Ovi4z5xWBO1q +NkCKgdAUQvQVzVtASVGBAoIBAQDSw2nvPFN4gGZ6OI+8j2gWtPcsrhSHS9ykxBeB +mB/HExYIe8k3EvClf2rnfwzuKgKyVMp7Ev7nH2jS/PGZq37QyXrw0NBGRnvJY0Ez +YB1KTgf9xaHMGMut5efNvv/cPwYriqosgJ0pdt0vvUAIQ6EBv+iDXXqJ1lQUSRYk +wKjFABi6TeJY4t9vC474KoXTDaHlwn9+TwnuRBk85wrZzlhK90J0iVa9/Eqeddsc +Z3CuTlc+NmcP3qvniYODq8nyVc0pKw+28AVYYEd3aJfgm+dpcB21L0oz7CaxH/Rz +FNONuQRaOzJrcuJsde/KG2X+MHs6hVMXXXWciPrJ2l+Cq7dnAoIBAQDRdwZDcgem +tJHLihCRzUl9PKip4ZA5757ZyTy6WMLR3wMS2cNTK8+bTrUa0SSC4WSI28pybFA7 +QdSR08c5Nd7jXcIrtqspgZKhb0E60i8VQHhh6ba/kyQjsEz9c/G1WquPK13j2vZ0 +79bomDwFJPsFzABU+sC0/F42ZVQzy9qXkjngjtmaGfrCc7X+pV28nEGtyxHci3L4 +XXfE2dOb+GBVZPLBVXwcthdRYsFuU9GMy2GH0zVtWPOcGRnlpx53Tqg7NIeR0Nm1 +K35EaK8PH92PsAr0Xza7vQHY4cPRz+RhDzjyGQtnhKf96U6gzzt4ZVbQ/UuzDBcL +PQ2DvUH+sqxBAoIBAEW5kiUsDu0xhTVv2tVll+jTK2ZjnLT5ut/jY2djHTgtrz9V +PEb1BBmsIoC9PljYGxZGCMpYiW2KrZIHTiIpYwXNcdeTLSPik3cXV+2YIXiAghJJ +PHKZzWAVS+97/YcubmsfL5cTYWrjQN9XO4TAYtaCV3iGB1DsT9p6J1I3Tl4F3yhb +NcN0IrjI2R5uauFchC/PfYAaw81ISBUm1iciJYF/dUO6X7DwcvsjQD6QVe3ESwZw +1v2gC7zIeHKp9WAvVHUHIubBVvNavqnZN01+JjtydNGI+IJe4Jn+WU9tF2OuTqtP +JCn50sBQ7+gr0j0aatn8W3XCXHNRua3niWtgRYcCggEAT7OzfWxhPuyMYV9qiKAN +a4ruPp3mjDUCQ6pP4jQuBT+PYtfbe8U63MSpIsgb1XVAFNdVBA70xGd7I/XqY3l9 +ExS08n8yR7vW+Hhl4KTjZ3m9lLwiXmj1omLOGM7KVRBoITUGJ9JEXyB3rM9oXyjA +H2eNZMh5FSTGEHqj/IV/6paoUSrp37os8VqoEHoJ3d+zGhcf98RT/e9KyGt+GmX6 ++eNMf4YwkJg07THfmkRoguNMfCtAtBfZsjbW5MyfShRy7PxC7ZgDju06wXr3yZB9 +dNQuhufH4s27azQUl7w8ETaCm5QuA7i1V2c0FPpljZ052JHZAQsDpbIYd11HREvm +QQKCAQEA0W7xNYoFvnyikdG0t266LLv1EkWDFdgkelGx/eGe/JZ+au3uTM94EssC +ni64XX2P8vK/te+c3jItYO4MRgnDJ7GW+bRnJFu2kBE0W4chx7vga0XApVCP+Ugg +owv5yf9cOAHFulvPefsU0snYStD3gNq77XDg0CwoyUkpeq+GiupoQ8tquMSsrEwp +ve5DtDip3cLHz2oVLB3mR4kKVwVwmOgO5RKq6N/H6Jxtf/Zk1I260dKr+Dv2MnDh +dysO4zH5YEt2ML3oY4zY8lu+I5bHCBR1updSny0B31WrXAJyfZpMx+HOwETFKa3B +v9AGKz0Jc2GOIRKHrCQ/WkZePetaYQ== +-----END PRIVATE KEY----- diff --git a/ms/py-executor/server.py b/ms/py-executor/server.py index 5c149d96b..f506e9446 100644 --- a/ms/py-executor/server.py +++ b/ms/py-executor/server.py @@ -33,21 +33,45 @@ _ONE_DAY_IN_SECONDS = 60 * 60 * 24 def serve(configuration: ScriptExecutorConfiguration): port = configuration.script_executor_property('port') - basic_auth = configuration.script_executor_property('auth') + authType = configuration.script_executor_property('authType') maxWorkers = configuration.script_executor_property('maxWorkers') - header_validator = RequestHeaderValidatorInterceptor( - 'authorization', basic_auth, grpc.StatusCode.UNAUTHENTICATED, - 'Access denied!') + if authType == 'tls-auth': + cert_chain_file = configuration.script_executor_property('certChain') + private_key_file = configuration.script_executor_property('privateKey') + logger.info("Setting GRPC server TLS authentication, cert file(%s) private key file(%s)", cert_chain_file, + private_key_file) + # read in key and certificate + with open(cert_chain_file, 'rb') as f: + certificate_chain = f.read() + with open(private_key_file, 'rb') as f: + private_key = f.read() - server = grpc.server(futures.ThreadPoolExecutor(max_workers=int(maxWorkers)), - interceptors=(header_validator,)) + # create server credentials + server_credentials = grpc.ssl_server_credentials(((private_key, certificate_chain),)) - BluePrintProcessing_pb2_grpc.add_BluePrintProcessingServiceServicer_to_server( - BluePrintProcessingServer(configuration), server) + # create server + server = grpc.server(futures.ThreadPoolExecutor(max_workers=int(maxWorkers))) + BluePrintProcessing_pb2_grpc.add_BluePrintProcessingServiceServicer_to_server( + BluePrintProcessingServer(configuration), server) - server.add_insecure_port('[::]:' + port) - server.start() + # add secure port using credentials + server.add_secure_port('[::]:' + port, server_credentials) + server.start() + else: + logger.info("Setting GRPC server base authentication") + basic_auth = configuration.script_executor_property('token') + header_validator = RequestHeaderValidatorInterceptor( + 'authorization', basic_auth, grpc.StatusCode.UNAUTHENTICATED, + 'Access denied!') + # create server with token authentication interceptors + server = grpc.server(futures.ThreadPoolExecutor(max_workers=int(maxWorkers)), + interceptors=(header_validator,)) + BluePrintProcessing_pb2_grpc.add_BluePrintProcessingServiceServicer_to_server( + BluePrintProcessingServer(configuration), server) + + server.add_insecure_port('[::]:' + port) + server.start() logger.info("Command Executor Server started on %s" % port) |