def __init__(self, certificate): if not isinstance(certificate, Certificate): if os.path.isfile(certificate): certificate = Certificate.loadPEM(open(certificate).read()) else: certificate = Certificate.loadPEM(certificate) self._original = certificate self.certificate = certificate.dumpPEM()
def main(self, reactor, options): certificates_path = FilePath(options["certificates-directory"]) ca = Certificate.loadPEM( certificates_path.child(b"cluster.crt").getContent()) # This is a hack; from_path should be more # flexible. https://clusterhq.atlassian.net/browse/FLOC-1865 control_credential = ControlCredential.from_path( certificates_path, b"service") top_service = MultiService() persistence = ConfigurationPersistenceService( reactor, options["data-path"]) persistence.setServiceParent(top_service) cluster_state = ClusterStateService(reactor) cluster_state.setServiceParent(top_service) api_service = create_api_service( persistence, cluster_state, serverFromString( reactor, options["port"]), rest_api_context_factory(ca, control_credential)) api_service.setServiceParent(top_service) amp_service = ControlAMPService( reactor, cluster_state, persistence, serverFromString( reactor, options["agent-port"]), amp_server_context_factory(ca, control_credential)) amp_service.setServiceParent(top_service) return main_for_service(reactor, top_service)
def main(self, reactor, options): certificates_path = FilePath(options["certificates-directory"]) ca = Certificate.loadPEM( certificates_path.child(b"cluster.crt").getContent()) # This is a hack; from_path should be more # flexible. https://clusterhq.atlassian.net/browse/FLOC-1865 control_credential = ControlCredential.from_path( certificates_path, b"service") top_service = MultiService() persistence = ConfigurationPersistenceService(reactor, options["data-path"]) persistence.setServiceParent(top_service) cluster_state = ClusterStateService(reactor) cluster_state.setServiceParent(top_service) api_service = create_api_service( persistence, cluster_state, serverFromString(reactor, options["port"]), rest_api_context_factory(ca, control_credential)) api_service.setServiceParent(top_service) amp_service = ControlAMPService( reactor, cluster_state, persistence, serverFromString(reactor, options["agent-port"]), amp_server_context_factory(ca, control_credential)) amp_service.setServiceParent(top_service) return main_for_service(reactor, top_service)
def test_ssl(self): """ When passed an SSL strports description, L{clientFromString} returns a L{SSL4ClientEndpoint} instance initialized with the values from the string. """ reactor = object() client = endpoints.clientFromString( reactor, "ssl:host=example.net:port=4321:privateKey=%s:" "certKey=%s:bindAddress=10.0.0.3:timeout=3:caCertsDir=%s" % (escapedPEMPathName, escapedPEMPathName, escapedCAsPathName)) self.assertIsInstance(client, endpoints.SSL4ClientEndpoint) self.assertIdentical(client._reactor, reactor) self.assertEquals(client._host, "example.net") self.assertEquals(client._port, 4321) self.assertEquals(client._timeout, 3) self.assertEquals(client._bindAddress, "10.0.0.3") certOptions = client._sslContextFactory self.assertIsInstance(certOptions, CertificateOptions) ctx = certOptions.getContext() self.assertIsInstance(ctx, ContextType) self.assertEquals(Certificate(certOptions.certificate), testCertificate) privateCert = PrivateCertificate(certOptions.certificate) privateCert._setPrivateKey(KeyPair(certOptions.privateKey)) self.assertEquals(privateCert, testPrivateCertificate) expectedCerts = [ Certificate.loadPEM(x.getContent()) for x in [casPath.child("thing1.pem"), casPath.child("thing2.pem")] if x.basename().lower().endswith('.pem') ] self.assertEquals([Certificate(x) for x in certOptions.caCerts], expectedCerts)
def connect(self, host=None, port=None, cert=None, key=None): ''' Connect to another portal somewhere. If retry is set, will attempt to reconnect with the target continuously. As of the time of this writing, you cannot stop a polling connection without taking down the portal. :param retry: continuously attempt to connect on drops or rejections :type retry: bool. ''' host = host if host else self.host port = port if port else self.port cert = cert if cert else self.certCa key = key if key else self.keyPrivate # ??? # the first term is the name the server is using in the cert (for now) ctx = optionsForClientTLS(u"pds.production", Certificate.loadPEM(cert), PrivateCertificate.loadPEM(key)) factory = RiffleClientFactory() SSL4ClientEndpoint(reactor, host, port, ctx,).connect(factory) print 'Connecting to ' + host + ':' + str(port) avatar = yield factory.login(self) defer.returnValue(Levy(avatar))
def get_configuration(options): """ Load and validate the configuration in the file specified by the given options. :param DatasetAgentOptions options: The dataset agent options specifying the location of the configuration. :return: A ``dict`` representing the configuration loaded from the file. """ agent_config = options[u'agent-config'] configuration = yaml.safe_load(agent_config.getContent()) validate_configuration(configuration=configuration) configuration['control-service'].setdefault('port', 4524) path = agent_config.parent() # This is a hack; from_path should be more # flexible. https://clusterhq.atlassian.net/browse/FLOC-1865 configuration['ca-certificate'] = Certificate.loadPEM( path.child(b"cluster.crt").getContent()) configuration['node-credential'] = NodeCredential.from_path(path, b"node") return configuration
def get_context_factory(cert_path, pkey_path): """OpenSSL context factory. Generates an OpenSSL context factory using Twisted's CertificateOptions class. This will keep a server cipher order. Args: cert_path (string): The path to the certificate file pkey_path (string): The path to the private key file Returns: twisted.internet.ssl.CertificateOptions: An OpenSSL context factory """ with open(cert_path) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(pkey_path) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original ciphers = AcceptableCiphers.fromOpenSSLCipherString(TLS_CIPHERS) cert_options = CertificateOptions( privateKey=private_key, certificate=certificate, raiseMinimumTo=TLSVersion.TLSv1_2, acceptableCiphers=ciphers, ) ctx = cert_options.getContext() ctx.use_certificate_chain_file(cert_path) ctx.set_options(SSL_OP_NO_RENEGOTIATION) return cert_options
def getCertificate(self, subject): log.msg(format='Retreving certificate for %(name)s', name=subject) certPath = self.publicPath.child(subject) if not certPath.exists(): raise CertificateNotFound cert = Certificate.loadPEM(certPath.getContent()) return defer.succeed(cert)
def _get_http_client(): response = yield treq.get(ca) pemdata = yield response.text() cert = Certificate.loadPEM(pemdata) policy = BrowserLikePolicyForHTTPS(trustRoot=cert) agent = Agent(reactor, contextFactory=policy) client = treq.client.HTTPClient(agent) returnValue(client)
def main(reactor): pemBytes = FilePath(b"ca-private-cert.pem").getContent() certificateAuthority = Certificate.loadPEM(pemBytes) myCertificate = PrivateCertificate.loadPEM(pemBytes) serverEndpoint = SSL4ServerEndpoint( reactor, 4321, myCertificate.options(certificateAuthority)) serverEndpoint.listen(Factory.forProtocol(ReportWhichClient)) return Deferred()
def loadPEM(cls, pemData): cert = X509Certificate() cert.__internalTwistedCert = Certificate.loadPEM(pemData) asn1cert = decoder.decode(pem.readPemFromFile(StringIO(pemData)), asn1Spec=rfc2459.Certificate())[0] cert.__internalAsn1 = asn1cert return cert
def main(reactor): pemBytes = FilePath(b"ca-private-cert.pem").getContent() certificateAuthority = Certificate.loadPEM(pemBytes) myCertificate = PrivateCertificate.loadPEM(pemBytes) serverEndpoint = SSL4ServerEndpoint( reactor, 4321, myCertificate.options(certificateAuthority) ) serverEndpoint.listen(Factory.forProtocol(ReportWhichClient)) return Deferred()
def main(reactor): pem = generate_certs.and_generate() caPem = FilePath(b"ca-private-cert.pem").getContent() clientEndpoint = SSL4ClientEndpoint( reactor, u"localhost", 4321, optionsForClientTLS(u"the-authority", Certificate.loadPEM(caPem), PrivateCertificate.loadPEM(pem)), ) clientEndpoint = SSL4ClientEndpoint( reactor, u"localhost", 4321, optionsForClientTLS(u"the-authority", Certificate.loadPEM(caPem), PrivateCertificate.loadPEM(pem)), ) proto = yield clientEndpoint.connect(Factory.forProtocol(SendAnyData)) yield proto.deferred
def getTlsAuthority_(self, startTlsCaCert): if startTlsCaCert is None: return None authorities = [str(cert) for cert in pem.parse_file(startTlsCaCert)] if len(authorities) != 1: raise Exception( ("The provided CA cert file, '{0}', " "contained {1} certificates. It must contain exactly one." ).format(startTlsCaCert, len(authorities))) return Certificate.loadPEM(authorities[0])
def getTlsAuthority_(self, startTlsCaCert): if startTlsCaCert is None: return None authorities = [str(cert) for cert in pem.parse_file(startTlsCaCert)] if len(authorities) != 1: raise Exception( ("The provided CA cert file, '{0}', " "contained {1} certificates. It must contain exactly one.").format( startTlsCaCert, len(authorities))) return Certificate.loadPEM(authorities[0])
def open(self, port=None, cert=None): ''' Listen for connections on the given port. ''' port = port if port else self.port cert = cert if cert else self.certCa ca = Certificate.loadPEM(cert) myCertificate = PrivateCertificate.loadPEM(cert) SSL4ServerEndpoint(reactor, port, myCertificate.options(ca)).listen(RiffleServerFactory(self))
def get_test_https_policy(): """Get a test IPolicyForHTTPS which trusts the test CA cert Returns: IPolicyForHTTPS """ ca_file = get_test_ca_cert_file() with open(ca_file) as stream: content = stream.read() cert = Certificate.loadPEM(content) trust_root = trustRootFromCertificates([cert]) return BrowserLikePolicyForHTTPS(trustRoot=trust_root)
def start_ssl_cmd_server(): with open(settings["Agent_Cert"], 'r') as certfile: certdata = certfile.read() if settings["Agent_Priv_Key"] != settings["Agent_Cert"]: with open(settings.get("Agent_Priv_Key"), 'r') as keyfile: certdata += keyfile.read() with open(settings.get("Broker_Cert"), 'r') as f: authdata = f.read() certificate = PrivateCertificate.loadPEM(certdata) authority = Certificate.loadPEM(authdata) factory = Factory.forProtocol(CommandHandler) reactor.listenSSL(int(settings.get("Command_Port")), factory, certificate.options(authority))
def start_ssl(self): log.debug("Enabling SSL with PKey: %s, Cert: %s", self.pkey, self.cert) check_ssl_keys() with open(configmanager.get_config_dir(self.cert)) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(configmanager.get_config_dir(self.pkey)) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD) options.getContext().set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) self.socket = reactor.listenSSL(self.port, self.site, options) log.info("Serving on %s:%s view at https://127.0.0.1:%s", "0.0.0.0", self.port, self.port)
def fromFilePath(cls, filePath): privatePath = filePath.child('private') publicPath = filePath.child('public') csrPath = filePath.child('csr') issuerPath = filePath.child('issuer') if issuerPath.exists(): issuer = issuerPath.getContent() key = KeyPair.loadPEM(privatePath.child(issuer).getContent()) cert = Certificate.loadPEM(publicPath.child(issuer).getContent()) store = cls(publicPath, privatePath, csrPath, key, cert, issuer) return store
def _create_tls_client_context(config, cbdir, log): """ Create a CertificateOptions object for use with TLS listening endpoints. """ # server hostname: The expected name of the remote host. hostname = config['hostname'] # explicit trust (certificate) root ca_certs = None if 'ca_certificates' in config: log.info("TLS client using explicit trust ({cnt_certs} certificates)", cnt_certs=len(config['ca_certificates'])) ca_certs = [] for cert_fname in [os.path.abspath(os.path.join(cbdir, x)) for x in (config['ca_certificates'])]: cert = crypto.load_certificate( crypto.FILETYPE_PEM, six.u(open(cert_fname, 'r').read()) ) log.info("TLS client trust root CA certificate loaded from '{fname}'", fname=cert_fname) ca_certs.append(cert) ca_certs = OpenSSLCertificateAuthorities(ca_certs) else: log.info("TLS client using platform trust") # client key/cert to use client_cert = None if 'key' in config: if 'certificate' not in config: raise Exception('TLS client key present, but certificate missing') key_fname = os.path.abspath(os.path.join(cbdir, config['key'])) with open(key_fname, 'r') as f: private_key = KeyPair.load(f.read(), format=crypto.FILETYPE_PEM) log.info("Loaded client TLS key from '{key_fname}'", key_fname=key_fname) cert_fname = os.path.abspath(os.path.join(cbdir, config['certificate'])) with open(cert_fname, 'r') as f: cert = Certificate.loadPEM(f.read(),) log.info("Loaded client TLS certificate from '{cert_fname}' (cn='{cert_cn}', sha256={cert_sha256}..)", cert_fname=cert_fname, cert_cn=cert.getSubject().CN, cert_sha256=cert.digest('sha256')[:12]) client_cert = PrivateCertificate.fromCertificateAndKeyPair(cert, private_key) else: if 'certificate' in config: log.warn('TLS client certificate present, but key is missing') # create TLS client context ctx = optionsForClientTLS(hostname, trustRoot=ca_certs, clientCertificate=client_cert) return ctx
def compute_tls_options(): ''' Returns TLS connection options. ''' # tls cert_path = '../cert/example.crt' cert_data = open(cert_path).read() certificate = Certificate.loadPEM(cert_data) return optionsForClientTLS( hostname=AUTHORITY, acceptableProtocols=[b'h2'], trustRoot=certificate, )
def create_agent(ca_cert, client_cert, client_key): ca_certificate = Certificate.loadPEM(FilePath(ca_cert).getContent()) client_certificate = PrivateCertificate.loadPEM( FilePath(client_cert).getContent() + b"\n" + FilePath(client_key).getContent()) customPolicy = BrowserLikePolicyForHTTPSWithClientCertificate( trustRoot=ca_certificate, clientCertificate=client_certificate) pool = HTTPConnectionPool(reactor, persistent=True) agent = Agent(reactor, customPolicy, pool=pool) return agent
def create_agent(ca_cert, client_cert, client_key): ca_certificate = Certificate.loadPEM(FilePath(ca_cert).getContent()) client_certificate = PrivateCertificate.loadPEM( FilePath(client_cert).getContent() + b"\n" + FilePath(client_key).getContent()) customPolicy = BrowserLikePolicyForHTTPSWithClientCertificate( trustRoot=ca_certificate, clientCertificate=client_certificate) pool = HTTPConnectionPool(reactor, persistent=True) pool.maxPersistentPerHost = CONNECTION_COUNT agent = Agent(reactor, customPolicy, pool=pool) return agent
def from_paths( cls, endpoint, private_key_path: FilePath, cert_path: FilePath ) -> "_TLSEndpointWrapper": """ Create an endpoint with the given private key and certificate paths on the filesystem. """ certificate = Certificate.loadPEM(cert_path.getContent()).original private_key = PrivateCertificate.loadPEM( cert_path.getContent() + b"\n" + private_key_path.getContent() ).privateKey.original certificate_options = CertificateOptions( privateKey=private_key, certificate=certificate ) return cls(endpoint=endpoint, context_factory=certificate_options)
def start_ssl(self): log.debug("Enabling SSL with PKey: %s, Cert: %s", self.pkey, self.cert) check_ssl_keys() with open(configmanager.get_config_dir(self.cert)) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(configmanager.get_config_dir(self.pkey)) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD) ctx = options.getContext() ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) ctx.use_certificate_chain_file(configmanager.get_config_dir(self.cert)) self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface) log.info("Serving on %s:%s view at https://%s:%s", self.interface, self.port, self.interface, self.port)
def certsFromBundle(path, x509=False): PEM_RE = re.compile( "-----BEGIN CERTIFICATE-----\r?.+?\r?" "-----END CERTIFICATE-----\r?\n?" "", re.DOTALL) if not os.path.isfile(path): log.warn("Attempted to load non-existent certificate bundle path %s" % path) return [] pems = FilePath(path).getContent() cstr = [match.group(0) for match in PEM_RE.finditer(pems)] certs = [Certificate.loadPEM(cert) for cert in cstr] if x509: certs = [cert.original for cert in certs] return certs
def certsFromBundle(path, x509=False): PEM_RE = re.compile( "-----BEGIN CERTIFICATE-----\r?.+?\r?" "-----END CERTIFICATE-----\r?\n?""", re.DOTALL) if not os.path.isfile(path): log.warn("Attempted to load non-existent certificate bundle path %s" % path) return [] pems = FilePath(path).getContent() cstr = [match.group(0) for match in PEM_RE.finditer(pems)] certs = [Certificate.loadPEM(cert) for cert in cstr] if x509: certs = [cert.original for cert in certs] return certs
def setUp(self): description = yield self._httpbin_process.server_description( reactor) self.baseurl = URL(scheme=u"https", host=description.host, port=description.port).asText() root = trustRootFromCertificates( [Certificate.loadPEM(description.cacert)], ) self.agent = Agent( reactor, contextFactory=BrowserLikePolicyForHTTPS(root), ) self.pool = HTTPConnectionPool(reactor, False)
def test_chainCerts(self): """ L{chainCerts} loads all but the first cert in a file. """ data = FilePath(__file__).sibling('data').child('certs') cert1 = data.child('cert1.pem').getContent() cert2 = data.child('cert2.pem').getContent() cert3 = data.child('cert3.pem').getContent() expected = [ Certificate.loadPEM(cert) for cert in [cert2, cert3]] chain = chainCerts(cert1 + '\n' + cert2 + '\n' + cert3) self.assertEqual(len(chain), 2) self.assertEqual( chain[0].digest('sha256'), expected[0].digest('sha256')) self.assertEqual( chain[1].digest('sha256'), expected[1].digest('sha256'))
def start_ssl(self): check_ssl_keys() log.debug('Enabling SSL with PKey: %s, Cert: %s', self.pkey, self.cert) with open(configmanager.get_config_dir(self.cert)) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(configmanager.get_config_dir(self.pkey)) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD) ctx = options.getContext() ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) ctx.use_certificate_chain_file(configmanager.get_config_dir(self.cert)) self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface) ip = self.socket.getHost().host ip = '[%s]' % ip if is_ipv6(ip) else ip log.info('Serving at https://%s:%s%s', ip, self.port, self.base)
def connect_to_one_broker_TLS(self, p_pyhouse_obj, p_broker): l_host = p_broker.BrokerAddress l_port = p_broker.BrokerPort l_username = p_broker.UserName l_password = p_broker.Password l_clientID = 'PyH-' + p_pyhouse_obj.Computer.Name LOG.info('Connecting via TLS...') # l_factory = protocol.Factory.forProtocol(echoclient.EchoClient) l_factory = PyHouseMqttFactory(p_pyhouse_obj, l_clientID, p_broker, l_username, l_password) l_certData = PEM_FILE.getContent() l_authority = Certificate.loadPEM(l_certData) l_options = optionsForClientTLS(l_host.decode('utf-8'), l_authority) l_endpoint = SSL4ClientEndpoint(p_pyhouse_obj.Twisted.Reactor, l_host, l_port, l_options) l_client = yield l_endpoint.connect(l_factory) l_done = defer.Deferred() l_client.connectionLost = lambda reason: l_done.callback(None) yield l_done
def _serviceDescription(self): """ Produce a description of the service we should start. """ ca = Certificate.loadPEM( FilePath(self.caPath.encode('utf-8')).getContent()) certBytes = FilePath(self.certPath.encode('utf-8')).getContent() cert = PrivateCertificate.loadPEM(certBytes) # Can't use PrivateCertificate.options until Twisted #6361 is fixed options = CertificateOptions( privateKey=cert.privateKey.original, certificate=cert.original, trustRoot=ca, extraCertChain=chainCerts(certBytes)) router = IndexRouter(store=self.store) return _ServiceDescription( reactor=reactor, port=self.port, interface=self.interface, options=options, router=router)
def test_unreadableCertificate(self): """ If a certificate in the directory is unreadable, L{endpoints._loadCAsFromDir} will ignore that certificate. """ class UnreadableFilePath(FilePath): def getContent(self): data = FilePath.getContent(self) # There is a duplicate of thing2.pem, so ignore anything that # looks like it. if data == casPath.child("thing2.pem").getContent(): raise IOError(EPERM) else: return data casPathClone = casPath.child("ignored").parent() casPathClone.clonePath = UnreadableFilePath self.assertEqual( [Certificate(x) for x in endpoints._loadCAsFromDir(casPathClone)], [Certificate.loadPEM(casPath.child("thing1.pem").getContent())])
def _get_ssl_context(self): client_ca = get_certificate(self.client_ca_cert_path) if not client_ca: try: ca = mTLS.generate_new_certificate(is_ca_generation_request=True, ca_cert_path=self.client_ca_cert_path, username="******") if ca is not None: save_certificate(self.client_ca_cert_path, ca) client_ca = ca except Exception as e: log.error("Exception: {}".format(e)) raise e client_ca_pem = "{}\n{}".format(base64.b64decode(client_ca.get('c')), base64.b64decode(client_ca.get('k'))) certificate_authority = Certificate.loadPEM(client_ca_pem) self.server_ca_cert_path = self.server_cert_path+"_ca" server_cert = get_certificate(self.server_cert_path) server_cert_ca = get_certificate(self.server_ca_cert_path) if not server_cert: try: if not server_cert_ca: ca = mTLS.generate_new_certificate(is_ca_generation_request=True, ca_cert_path=self.server_ca_cert_path, username="******") if ca is not None: save_certificate(self.server_ca_cert_path, ca) _server_cert = mTLS.generate_new_certificate(ca_cert_path=self.server_ca_cert_path, username="******", ip=self.ip) if _server_cert is not None: save_certificate(self.server_cert_path, _server_cert) server_cert = _server_cert else: raise Exception("Server Certificate generation failed. Cert:{}".format(_server_cert)) except Exception as e: log.error("Exception: {}".format(e)) raise e server_cert_pem = "{}\n{}".format(base64.b64decode(server_cert.get('c')), base64.b64decode(server_cert.get('k'))) server_cert = PrivateCertificate.loadPEM(server_cert_pem) return server_cert.options(certificate_authority)
def treq_with_authentication(reactor, ca_path, user_cert_path, user_key_path): """ Create a ``treq``-API object that implements the REST API TLS authentication. That is, validating the control service as well as presenting a certificate to the control service for authentication. :param reactor: The reactor to use. :param FilePath ca_path: Absolute path to the public cluster certificate. :param FilePath user_cert_path: Absolute path to the user certificate. :param FilePath user_key_path: Absolute path to the user private key. :return: ``treq`` compatible object. """ ca = Certificate.loadPEM(ca_path.getContent()) user_credential = UserCredential.from_files(user_cert_path, user_key_path) policy = ControlServicePolicy( ca_certificate=ca, client_credential=user_credential.credential) return HTTPClient(Agent(reactor, contextFactory=policy))
def objectsFromPEM(pemdata): """ Load some objects from a PEM. """ certificates = [] keys = [] for line in pemdata.split("\n"): if line.startswith('-----BEGIN'): if 'CERTIFICATE' in line: blobs = certificates else: blobs = keys blobs.append('') blobs[-1] += line blobs[-1] += '\n' keys = [KeyPair.load(key, FILETYPE_PEM) for key in keys] certificates = [ Certificate.loadPEM(certificate) for certificate in certificates ] return PEMObjects(keys=keys, certificates=certificates)
def treq_with_authentication(reactor, ca_path, user_cert_path, user_key_path): """ Create a ``treq``-API object that implements the REST API TLS authentication. That is, validating the control service as well as presenting a certificate to the control service for authentication. :param reactor: The reactor to use. :param FilePath ca_path: Absolute path to the public cluster certificate. :param FilePath user_cert_path: Absolute path to the user certificate. :param FilePath user_key_path: Absolute path to the user private key. :return: ``treq`` compatible object. """ ca = Certificate.loadPEM(ca_path.getContent()) user_credential = UserCredential.from_files(user_cert_path, user_key_path) policy = ControlServicePolicy(ca_certificate=ca, client_credential=user_credential.credential) return HTTPClient(Agent(reactor, contextFactory=policy))
def _context_factory_and_credential(path, host, port): """ Load a TLS context factory for the AMP client from the path where configuration and certificates live. The CA certificate and node private key and certificate are expected to be siblings of the configuration file. :param FilePath path: Path to directory where configuration lives. :param bytes host: The host we will be connecting to. :param int port: The port we will be connecting to. :return: ``_TLSContext`` instance. """ ca = Certificate.loadPEM(path.child(b"cluster.crt").getContent()) # This is a hack; from_path should be more # flexible. https://clusterhq.atlassian.net/browse/FLOC-1865 node_credential = NodeCredential.from_path(path, b"node") policy = ControlServicePolicy(ca_certificate=ca, client_credential=node_credential.credential) return _TLSContext(context_factory=policy.creatorForNetloc(host, port), node_credential=node_credential)
def chainCerts(data): """ Matches and returns any certificates found except the first match. Regex code copied from L{twisted.internet.endpoints._parseSSL}. Related ticket: https://twistedmatrix.com/trac/ticket/7732 @type path: L{bytes} @param data: PEM-encoded data containing the certificates. @rtype: L{list} containing L{Certificate}s. """ matches = re.findall( r'(-----BEGIN CERTIFICATE-----\n.+?\n-----END CERTIFICATE-----)', data, flags=re.DOTALL) chainCertificates = [ Certificate.loadPEM(chainCertPEM).original for chainCertPEM in matches] return chainCertificates[1:]
def objectsFromPEM(pemdata): """ Load some objects from a PEM. """ certificates = [] keys = [] blobs = [b""] for line in pemdata.split(b"\n"): if line.startswith(b'-----BEGIN'): if b'CERTIFICATE' in line: blobs = certificates else: blobs = keys blobs.append(b'') blobs[-1] += line blobs[-1] += b'\n' keys = [KeyPair.load(key, FILETYPE_PEM) for key in keys] certificates = [Certificate.loadPEM(certificate) for certificate in certificates] return PEMObjects(keys=keys, certificates=certificates)
def treq_with_authentication(reactor, certificates_path): """ Create a ``treq``-API object that implements the REST API TLS authentication. That is, validating the control service as well as presenting a certificate to the control service for authentication. :param reactor: The reactor to use. :param FilePath certificates_path: Directory where certificates and private key can be found. :return: ``treq`` compatible object. """ ca = Certificate.loadPEM( certificates_path.child(b"cluster.crt").getContent()) # This is a hack; from_path should be more # flexible. https://clusterhq.atlassian.net/browse/FLOC-1865 user_credential = UserCredential.from_path(certificates_path, u"user") policy = ControlServicePolicy(ca_certificate=ca, client_credential=user_credential.credential) return HTTPClient(Agent(reactor, contextFactory=policy))
def treq_with_authentication(reactor, certificates_path): """ Create a ``treq``-API object that implements the REST API TLS authentication. That is, validating the control service as well as presenting a certificate to the control service for authentication. :param reactor: The reactor to use. :param FilePath certificates_path: Directory where certificates and private key can be found. :return: ``treq`` compatible object. """ ca = Certificate.loadPEM( certificates_path.child(b"cluster.crt").getContent()) # This is a hack; from_path should be more # flexible. https://clusterhq.atlassian.net/browse/FLOC-1865 user_credential = UserCredential.from_path(certificates_path, u"user") policy = ControlServicePolicy( ca_certificate=ca, client_credential=user_credential.credential) return HTTPClient(Agent(reactor, contextFactory=policy))
def test_ssl(self): """ When passed an SSL strports description, L{clientFromString} returns a L{SSL4ClientEndpoint} instance initialized with the values from the string. """ reactor = object() client = endpoints.clientFromString( reactor, "ssl:host=example.net:port=4321:privateKey=%s:" "certKey=%s:bindAddress=10.0.0.3:timeout=3:caCertsDir=%s" % (escapedPEMPathName, escapedPEMPathName, escapedCAsPathName)) self.assertIsInstance(client, endpoints.SSL4ClientEndpoint) self.assertIdentical(client._reactor, reactor) self.assertEqual(client._host, "example.net") self.assertEqual(client._port, 4321) self.assertEqual(client._timeout, 3) self.assertEqual(client._bindAddress, "10.0.0.3") certOptions = client._sslContextFactory self.assertIsInstance(certOptions, CertificateOptions) ctx = certOptions.getContext() self.assertIsInstance(ctx, ContextType) self.assertEqual(Certificate(certOptions.certificate), testCertificate) privateCert = PrivateCertificate(certOptions.certificate) privateCert._setPrivateKey(KeyPair(certOptions.privateKey)) self.assertEqual(privateCert, testPrivateCertificate) expectedCerts = [ Certificate.loadPEM(x.getContent()) for x in [casPath.child("thing1.pem"), casPath.child("thing2.pem")] if x.basename().lower().endswith('.pem') ] self.assertEqual(sorted((Certificate(x) for x in certOptions.caCerts), key=lambda cert: cert.digest()), sorted(expectedCerts, key=lambda cert: cert.digest()))
def getPolicyForHTTPS(trustRoot=None): if SKIP_SSL_CHECK: log.info("---------------------------------------") log.info("SKIPPING SSL CERT VERIFICATION!!!") log.info("I assume you know WHAT YOU ARE DOING...") log.info("---------------------------------------") class WebClientContextFactory(ClientContextFactory): """ A web context factory which ignores the hostname and port and does no certificate verification. """ def getContext(self, hostname, port): return ClientContextFactory.getContext(self) contextFactory = WebClientContextFactory() return contextFactory if isinstance(trustRoot, str): trustRoot = Certificate.loadPEM(FilePath(trustRoot).getContent()) return BrowserLikePolicyForHTTPS(trustRoot)
reactor.stop() def sendRequest(self): request_headers = [ (':method', 'GET'), (':authority', AUTHORITY), (':scheme', 'https'), (':path', PATH), ('user-agent', 'hyper-h2/1.0.0'), ] self.conn.send_headers(1, request_headers, end_stream=True) self.request_made = True certData = open('cert/example.crt').read() certificate = Certificate.loadPEM(certData) options = optionsForClientTLS( hostname=AUTHORITY, acceptableProtocols=[b'h2'], trustRoot=certificate, ) class ShowCertificate(Protocol): def connectionMade(self): self.transport.write(b"GET / HTTP/1.0\r\n\r\n") self.done = defer.Deferred() def dataReceived(self, data): certificate = Certificate(self.transport.getPeerCertificate())
from twisted.python.filepath import FilePath from twisted.test.proto_helpers import ( MemoryReactor, RaisingMemoryReactor, StringTransport) from twisted.internet.protocol import ClientFactory, Protocol from twisted.internet.address import IPv4Address, IPv6Address from twisted.internet import (_endpointspy3 as endpoints, error, defer, interfaces, reactor) from twisted.test import __file__ as testInitPath pemPath = FilePath(testInitPath.encode("utf-8")).sibling(b"server.pem") try: from twisted.test.test_sslverify import makeCertificate from twisted.internet.ssl import (CertificateOptions, Certificate, PrivateCertificate) testCertificate = Certificate.loadPEM(pemPath.getContent()) testPrivateCertificate = PrivateCertificate.loadPEM(pemPath.getContent()) skipSSL = False except ImportError: skipSSL = "OpenSSL is required to construct SSL Endpoints" class TestProtocol(Protocol): """ Protocol whose only function is to callback deferreds on the factory when it is connected or disconnected. """ def __init__(self): self.data = []
'..', '..', '..', '..', 'router', '.crossbar', 'intermediate.cert.pem', ) tls_transport = { "type": "websocket", "url": "wss://127.0.0.1:8083/ws", "endpoint": SSL4ClientEndpoint( reactor, '127.0.0.1', 8083, optionsForClientTLS( 'localhost', # XXX why do I need BOTH the intermediate and actual # cert? Did I create the CA/intermediate certificates # incorrectly? trustRoot=trustRootFromCertificates( [ Certificate.loadPEM(open(cert_fname).read()), Certificate.loadPEM(open(inter_cert_fname).read()), ] ), ), ) } unix_transport = { "type": "websocket", "url": "ws://localhost/ws", "endpoint": UNIXClientEndpoint( reactor, os.path.join( os.path.split(__file__)[0], '..', '..', '..', '..', 'router', '.crossbar', 'intermediate.cert.pem',
def _create_tls_server_context(config, cbdir, log): """ Create a CertificateOptions object for use with TLS listening endpoints. """ # server private key key_filepath = abspath(join(cbdir, config['key'])) log.info("Loading server TLS key from {key_filepath}", key_filepath=key_filepath) with open(key_filepath) as key_file: # server certificate (but only the server cert, no chain certs) cert_filepath = abspath(join(cbdir, config['certificate'])) log.info("Loading server TLS certificate from {cert_filepath}", cert_filepath=cert_filepath) with open(cert_filepath) as cert_file: key = KeyPair.load(key_file.read(), crypto.FILETYPE_PEM).original cert = Certificate.loadPEM(cert_file.read()).original # list of certificates that complete your verification chain extra_certs = None if 'chain_certificates' in config: extra_certs = [] for fname in config['chain_certificates']: extra_cert_filepath = abspath(join(cbdir, fname)) with open(extra_cert_filepath, 'r') as f: extra_certs.append(Certificate.loadPEM(f.read()).original) log.info("Loading server TLS chain certificate from {extra_cert_filepath}", extra_cert_filepath=extra_cert_filepath) # list of certificate authority certificate objects to use to verify the peer's certificate ca_certs = None if 'ca_certificates' in config: ca_certs = [] for fname in config['ca_certificates']: ca_cert_filepath = abspath(join(cbdir, fname)) with open(ca_cert_filepath, 'r') as f: ca_certs.append(Certificate.loadPEM(f.read()).original) log.info("Loading server TLS CA certificate from {ca_cert_filepath}", ca_cert_filepath=ca_cert_filepath) # ciphers we accept # # We prefer to make every single cipher (6 in total) _explicit_ (to reduce chances either we or the pattern-matching # language inside OpenSSL messes up) and drop support for Windows XP (we do WebSocket anyway). # # We don't use AES256 and SHA384, to reduce number of ciphers and since the additional # security gain seems not worth the additional performance drain. # # We also don't use ECDSA, since EC certificates a rare in the wild. # # The effective list of ciphers determined from an OpenSSL cipher string: # # openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:' # # References: # # * https://www.ssllabs.com/ssltest/analyze.html?d=myserver.com # * http://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ # * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT # * https://wiki.mozilla.org/Talk:Security/Server_Side_TLS # if 'ciphers' in config: log.info("Using explicit TLS ciphers from config") crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString(config['ciphers']) else: log.info("Using secure default TLS ciphers") crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString( # AEAD modes (GCM) # 'ECDHE-ECDSA-AES128-GCM-SHA256:' 'ECDHE-RSA-AES128-GCM-SHA256:' # 'ECDHE-ECDSA-AES256-GCM-SHA384:' # 'ECDHE-RSA-AES256-GCM-SHA384:' 'DHE-RSA-AES128-GCM-SHA256:' # 'DHE-RSA-AES256-GCM-SHA384:' # CBC modes 'ECDHE-RSA-AES128-SHA256:' 'DHE-RSA-AES128-SHA256:' 'ECDHE-RSA-AES128-SHA:' 'DHE-RSA-AES128-SHA:' ) # DH modes require a parameter file if 'dhparam' in config: dhpath = FilePath(abspath(join(cbdir, config['dhparam']))) dh_params = DiffieHellmanParameters.fromFile(dhpath) else: dh_params = None log.warn("No OpenSSL DH parameter file set - DH cipher modes will be deactive!") # create a TLS context factory # see: https://twistedmatrix.com/documents/current/api/twisted.internet.ssl.CertificateOptions.html ctx = CertificateOptions( privateKey=key, certificate=cert, extraCertChain=extra_certs, verify=(ca_certs is not None), caCerts=ca_certs, dhParameters=dh_params, acceptableCiphers=crossbar_ciphers, # TLS hardening method=TLSv1_2_METHOD, enableSingleUseKeys=True, enableSessions=False, enableSessionTickets=False, fixBrokenPeers=False, ) # Without a curve being set, ECDH won't be available even if listed # in acceptable ciphers! # # The curves available in OpenSSL can be listed: # # openssl ecparam -list_curves # # prime256v1: X9.62/SECG curve over a 256 bit prime field # # This is elliptic curve "NIST P-256" from here # http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf # # This seems to be the most widely used curve # # http://crypto.stackexchange.com/questions/11310/with-openssl-and-ecdhe-how-to-show-the-actual-curve-being-used # # and researchers think it is "ok" (other than wrt timing attacks etc) # # https://twitter.com/hyperelliptic/status/394258454342148096 # if ctx._ecCurve is None: log.warn("No OpenSSL elliptic curve set - EC cipher modes will be deactive!") else: if ctx._ecCurve.snName != "prime256v1": log.info("OpenSSL is using elliptic curve {curve}", curve=ctx._ecCurve.snName) else: log.info("OpenSSL is using elliptic curve prime256v1 (NIST P-256)") return ctx
def _create_tls_server_context(config, cbdir, log): """ Create a CertificateOptions object for use with TLS listening endpoints. """ # server private key key_filepath = abspath(join(cbdir, config['key'])) log.info("Loading server TLS key from {key_filepath}", key_filepath=key_filepath) with open(key_filepath) as key_file: # server certificate (but only the server cert, no chain certs) cert_filepath = abspath(join(cbdir, config['certificate'])) log.info("Loading server TLS certificate from {cert_filepath}", cert_filepath=cert_filepath) with open(cert_filepath) as cert_file: key = KeyPair.load(key_file.read(), crypto.FILETYPE_PEM).original cert = Certificate.loadPEM(cert_file.read()).original # list of certificates that complete your verification chain extra_certs = None if 'chain_certificates' in config: extra_certs = [] for fname in config['chain_certificates']: extra_cert_filepath = abspath(join(cbdir, fname)) with open(extra_cert_filepath, 'r') as f: extra_certs.append(Certificate.loadPEM(f.read()).original) log.info( "Loading server TLS chain certificate from {extra_cert_filepath}", extra_cert_filepath=extra_cert_filepath) # list of certificate authority certificate objects to use to verify the peer's certificate ca_certs = None if 'ca_certificates' in config: ca_certs = [] for fname in config['ca_certificates']: ca_cert_filepath = abspath(join(cbdir, fname)) with open(ca_cert_filepath, 'r') as f: ca_certs.append(Certificate.loadPEM(f.read()).original) log.info( "Loading server TLS CA certificate from {ca_cert_filepath}", ca_cert_filepath=ca_cert_filepath) # ciphers we accept # # We prefer to make every single cipher (6 in total) _explicit_ (to reduce chances either we or the pattern-matching # language inside OpenSSL messes up) and drop support for Windows XP (we do WebSocket anyway). # # We don't use AES256 and SHA384, to reduce number of ciphers and since the additional # security gain seems not worth the additional performance drain. # # We also don't use ECDSA, since EC certificates a rare in the wild. # # The effective list of ciphers determined from an OpenSSL cipher string: # # openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:' # # References: # # * https://www.ssllabs.com/ssltest/analyze.html?d=myserver.com # * http://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ # * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT # * https://wiki.mozilla.org/Talk:Security/Server_Side_TLS # if 'ciphers' in config: log.info("Using explicit TLS ciphers from config") crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString( config['ciphers']) else: log.info("Using secure default TLS ciphers") crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString( # AEAD modes (GCM) # 'ECDHE-ECDSA-AES128-GCM-SHA256:' 'ECDHE-RSA-AES128-GCM-SHA256:' # 'ECDHE-ECDSA-AES256-GCM-SHA384:' # 'ECDHE-RSA-AES256-GCM-SHA384:' 'DHE-RSA-AES128-GCM-SHA256:' # 'DHE-RSA-AES256-GCM-SHA384:' # CBC modes 'ECDHE-RSA-AES128-SHA256:' 'DHE-RSA-AES128-SHA256:' 'ECDHE-RSA-AES128-SHA:' 'DHE-RSA-AES128-SHA:') # DH modes require a parameter file if 'dhparam' in config: dhpath = FilePath(abspath(join(cbdir, config['dhparam']))) dh_params = DiffieHellmanParameters.fromFile(dhpath) else: dh_params = None log.warn( "No OpenSSL DH parameter file set - DH cipher modes will be deactive!" ) ctx = CertificateOptions( privateKey=key, certificate=cert, extraCertChain=extra_certs, verify=(ca_certs is not None), caCerts=ca_certs, dhParameters=dh_params, acceptableCiphers=crossbar_ciphers, # Disable SSLv3 and TLSv1 -- only allow TLSv1.1 or higher # # We are using Twisted private stuff (from twisted.internet._sslverify import TLSVersion), # as OpenSSL.SSL.TLSv1_1_METHOD wont work: # # [ERROR] File "../twisted/internet/_sslverify.py", line 1530, in __init__ # if raiseMinimumTo > self._defaultMinimumTLSVersion: # builtins.TypeError: '>' not supported between instances of 'int' and 'NamedConstant' # raiseMinimumTo=TLSVersion.TLSv1_1, # TLS hardening enableSingleUseKeys=True, enableSessions=False, enableSessionTickets=False, fixBrokenPeers=False, ) # Without a curve being set, ECDH won't be available even if listed # in acceptable ciphers! # # The curves available in OpenSSL can be listed: # # openssl ecparam -list_curves # # prime256v1: X9.62/SECG curve over a 256 bit prime field # # This is elliptic curve "NIST P-256" from here # http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf # # This seems to be the most widely used curve # # http://crypto.stackexchange.com/questions/11310/with-openssl-and-ecdhe-how-to-show-the-actual-curve-being-used # # and researchers think it is "ok" (other than wrt timing attacks etc) # # https://twitter.com/hyperelliptic/status/394258454342148096 # if False: # FIXME: this doesn't work anymore with Twisted 18.4. (there now seems more complex machinery # in self._ecChooser) if ctx._ecCurve is None: log.warn( "No OpenSSL elliptic curve set - EC cipher modes will be deactive!" ) else: if ctx._ecCurve.snName != "prime256v1": log.info("OpenSSL is using elliptic curve {curve}", curve=ctx._ecCurve.snName) else: log.info( "OpenSSL is using elliptic curve prime256v1 (NIST P-256)") return ctx
def _get_digest(cert): from twisted.internet.ssl import Certificate return Certificate.loadPEM(cert).digest()
def _getCert(self): """ Get the SSL certificate from an Axiom store directory. """ certFile = FilePath(self.dbdir).child('files').child('server.pem') return Certificate.loadPEM(certFile.getContent())
def _certificates_for_authority_and_server(service_identity, key_size=1024): """ Create a self-signed CA certificate and server certificate signed by the CA. :param service_identity: The identity (hostname) of the server. :type service_identity: :py:class:`unicode` :param key_size: (optional) The size of CA's and server's private RSA keys. Defaults to 1024 bits, which is the minimum allowed by OpenSSL Contexts at the default security level as of 1.1. :type key_size: :py:class:`int` :return: a 3-tuple of ``(certificate_authority_certificate, server_private_key, server_certificate)``. :rtype: :py:class:`tuple` of (:py:class:`sslverify.Certificate`, :py:class:`OpenSSL.crypto.PKey`, :py:class:`OpenSSL.crypto.X509`) """ common_name_for_ca = x509.Name( [x509.NameAttribute(NameOID.COMMON_NAME, u'Testing Example CA')]) common_name_for_server = x509.Name( [x509.NameAttribute(NameOID.COMMON_NAME, u'Testing Example Server')]) one_day = datetime.timedelta(1, 0, 0) private_key_for_ca = rsa.generate_private_key(public_exponent=65537, key_size=key_size, backend=default_backend()) public_key_for_ca = private_key_for_ca.public_key() ca_certificate = (x509.CertificateBuilder().subject_name( common_name_for_ca).issuer_name(common_name_for_ca).not_valid_before( datetime.datetime.today() - one_day).not_valid_after(datetime.datetime.today() + one_day).serial_number( x509.random_serial_number()). public_key(public_key_for_ca).add_extension( x509.BasicConstraints(ca=True, path_length=9), critical=True, ).sign(private_key=private_key_for_ca, algorithm=hashes.SHA256(), backend=default_backend())) private_key_for_server = rsa.generate_private_key( public_exponent=65537, key_size=key_size, backend=default_backend()) public_key_for_server = private_key_for_server.public_key() server_certificate = ( x509.CertificateBuilder().subject_name(common_name_for_server). issuer_name(common_name_for_ca).not_valid_before( datetime.datetime.today() - one_day).not_valid_after(datetime.datetime.today() + one_day).serial_number( x509.random_serial_number()). public_key(public_key_for_server).add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, ).add_extension( x509.SubjectAlternativeName([x509.DNSName(service_identity)]), critical=True, ).sign(private_key=private_key_for_ca, algorithm=hashes.SHA256(), backend=default_backend())) ca_self_cert = Certificate.loadPEM( ca_certificate.public_bytes(Encoding.PEM)) pkey = PKey.from_cryptography_key(private_key_for_server) x509_server_certificate = X509.from_cryptography(server_certificate) return ca_self_cert, pkey, x509_server_certificate