GithubHelp home page GithubHelp logo

canonical / tls-certificates-interface Goto Github PK

View Code? Open in Web Editor NEW
2.0 2.0 6.0 529 KB

Library for charm providers and requirers of x.509 certificates.

Home Page: https://charmhub.io/tls-certificates-interface/libraries/tls_certificates

License: Apache License 2.0

Python 100.00%
juju tls x509

tls-certificates-interface's People

Contributors

danielarndt avatar delgod avatar dependabot[bot] avatar dstathis avatar gatici avatar ghislainbourgeois avatar gruyaume avatar kayra1 avatar lucabello avatar marcoppenheimer avatar mehdi-bendriss avatar renovate[bot] avatar saltiyazan avatar sanchezfdezjavier avatar sed-i avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

tls-certificates-interface's Issues

Allow for multiple applications to relate to the same `tls-certificates` provider

Issue

  • e.g:
    • Model with 3 applications. zookeeper, kafka, tls-certificates-operator
    • We would like to have TLS on zookeeper, so we juju relate tls-certificates-operator zookeeper - works great
    • We would like to have TLS on kafka, from the same CA as signed ZooKeeper so that they can communicate, so we juju relate tls-certificates-operator kafka - fails

Error Logs

unit-tls-certificates-operator-4: 12:55:36 ERROR unit.tls-certificates-operator/4.juju-log certificates:73: Uncaught exception while in charm code:
Traceback (most recent call last):
  File "./src/charm.py", line 441, in <module>
    main(TLSCertificatesOperatorCharm)
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/venv/ops/main.py", line 431, in main
    _emit_charm_event(charm, dispatcher.event_name)
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/venv/ops/main.py", line 142, in _emit_charm_event
    event_to_emit.emit(*args, **kwargs)
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/venv/ops/framework.py", line 316, in emit
    framework._emit(event)
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/venv/ops/framework.py", line 784, in _emit
    self._reemit(event_path)
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/venv/ops/framework.py", line 857, in _reemit
    custom_handler(event)
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/lib/charms/tls_certificates_interface/v1/tls_certificates.py", line 910, in _on_relation_chang
ed
    for certificate_creation_request in self._provider_certificates
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/lib/charms/tls_certificates_interface/v1/tls_certificates.py", line 738, in _provider_certific
ates
    relation = self.model.get_relation(self.relationship_name)
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/venv/ops/model.py", line 246, in get_relation
    return self.relations._get_unique(relation_name, relation_id)
  File "/var/lib/juju/agents/unit-tls-certificates-operator-4/charm/venv/ops/model.py", line 622, in _get_unique
    raise TooManyRelatedAppsError(relation_name, num_related, 1)
ops.model.TooManyRelatedAppsError: Too many remote applications on certificates (2 > 1)
unit-tls-certificates-operator-4: 12:55:36 ERROR juju.worker.uniter.operation hook "certificates-relation-changed" (via hook dispatching script: dispatch) failed:
 exit status 1
unit-tls-certificates-operator-4: 12:55:36 INFO juju.worker.uniter awaiting error resolution for "relation-changed" hook

Likely Cause of Issue

  • The problem likely arises from not expecting multiple related applications:
    relation = self.model.get_relation(self.relationship_name)

Expected Behavior / Request

  • Allow support for multiple related applications, signing each application with the same CA, passing that CA across the relation data

SSL routines::wrong version number

Bug Description

Since having fetched v12, v13 versions of the lib, I'm coming across the following error as in subject regularly when fetching new certificates.

To Reproduce

Requesting certificates on an LXD-hosted unit, that are to be tested for HTTPS connection via CURL

Environment

See pipeline https://github.com/canonical/opensearch-dashboards-operator/actions/runs/8909789680/job/24469535396

Relevant log output

subprocess.CalledProcessError: Command '['bash', '-c', 'curl  -XPOST -H "Content-Type: application/json" -H "osd-xsrf: true" -H "Accept: application/json" https://10.231.98.161:5601/auth/login -d \'{"username":"kibanaserver","password": "1NrW1i7UR1G27i6zeMCCw4bHq1mVSck6"}\' --cacert ca.pem --verbose']' returned non-zero exit status 35.
----------------------------- Captured stderr call -----------------------------
Could not create directory '/home/runner/.ssh'.
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 10.231.98.161:5601...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 10.231.98.161 (10.231.98.161) port 5601 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: ca.pem
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* (5454) (IN), , Unknown (72):
{ [5 bytes data]
* error:0A00010B:SSL routines::wrong version number

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
* Closing connection 0
curl: (35) error:0A00010B:SSL routines::wrong version number

Additional context

No response

[v2.6] `certificates-relation-changed` fails for non-leader requirer units

When the requirer side of the relation has more than one unit, i.e. when the tls_certificates lib is run on non leader units, it fails for:

  File "/var/lib/juju/agents/unit-am-1/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 1365, in _on_relation_changed
    secret = self.charm.app.add_secret(
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 427, in add_secret
    id = self._backend.secret_add(
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 3119, in secret_add
    result = self._run('secret-add', *args, return_output=True)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 2695, in _run
    raise ModelError(e.stderr)
ops.model.ModelError: ERROR this unit is not the leader

Could/should the lib use unit instead of app? (self.charm.unit.add_secret)

Full Traceback:

unit-am-1: 09:14:08.602 DEBUG unit.am/1.juju-log certificates:9: Emitting Juju event certificates_relation_changed.
unit-am-1: 09:14:08.643 ERROR unit.am/1.juju-log certificates:9: Uncaught exception while in charm code:
Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 2693, in _run
    result = subprocess.run(args, **kwargs)  # type: ignore
  File "/usr/lib/python3.8/subprocess.py", line 516, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('/var/lib/juju/tools/unit-am-1/secret-get', '--label', 'afd8c2bccf834997afce12c2706d2ede------BEGIN CERTIFICATE REQUEST-----\nMIIC4DCCAcgCAQAwPjENMAsGA1UEAwwEYW0vMTEtMCsGA1UELQwkZmJlYmZkMmMt\nMWE4My00ZDU5LWFiYmYtYzEyNzhlNThmNzc1MIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEAr/1OM2Jdh8IpqhA74xvsFOJZhel6nkJMVkO3zPtX8Ghz65z1\nl4bmoP2bkwEOI1n9tyEmzObHKh30KmnMMGby/1FVOd9MlQ5+jnF3uO5yTcDdO721\n+4qPuzOEfcm46zwVnqskB2yTSNAp8YrItWbT9L1iHm/Hzkw7IYd5yhSZVIDCkdTg\nX2Buifc++SDIurDGwUbHmgGkqJwgYglaU2HfBe5rzGTXKQ6bOZeWpuVvm11j1bU9\ncVyWvDmj9wY9un+C2FEeFpGfuQn5VEmcovuR1jRmu5vr2cvCpEj6tQAO9IGOCl3s\n0skaSmb9bSd91rftpblmZcjcBV6oKQK7Uag0BQIDAQABoF0wWwYJKoZIhvcNAQkO\nMU4wTDBKBgNVHREEQzBBgj9hbS0xLmFtLWVuZHBvaW50cy50ZXN0LXByb21ldGhl\ndXMtYWxlcnRzLTMyazQuc3ZjLmNsdXN0ZXIubG9jYWwwDQYJKoZIhvcNAQELBQAD\nggEBAI66l+73jTigQvvUNs/cfWGQIPj18ED6pXWZcBjrUGueM47JXBP8hvZx5JuY\nw/myI90LPZMV/z7HZVJtadv9mpF3mefEtY5ul1liO4PG/47iQnyQmzI61revsUex\nqiCOB6WChdxdoBmHhGaL7VnWBajHZ+QL+I1Xo0hYdcwNE+vJqTKXwy6cI9bNNkVV\nIpxOjL+AYUn5qt3s1qkYAkCZvSmNswwlh5gSFAEBrO8fUtEj9i1Fwo8iq4HbJ6vZ\n1RWFaNDwNjgZ09TGm47xBk39XD9UpdOrBBYEvG4NOljmSeFBy3OeDZ/phzBLOsuc\nB19EN9zx6B6uqV7Io2s0nSbtD9Y=\n-----END CERTIFICATE REQUEST-----', '--format=json')' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 3049, in secret_get
    result = self._run('secret-get', *args, return_output=True, use_json=True)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 2695, in _run
    raise ModelError(e.stderr)
ops.model.ModelError: ERROR consumer label "afd8c2bccf834997afce12c2706d2ede------BEGIN CERTIFICATE REQUEST-----\nMIIC4DCCAcgCAQAwPjENMAsGA1UEAwwEYW0vMTEtMCsGA1UELQwkZmJlYmZkMmMt\nMWE4My00ZDU5LWFiYmYtYzEyNzhlNThmNzc1MIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEAr/1OM2Jdh8IpqhA74xvsFOJZhel6nkJMVkO3zPtX8Ghz65z1\nl4bmoP2bkwEOI1n9tyEmzObHKh30KmnMMGby/1FVOd9MlQ5+jnF3uO5yTcDdO721\n+4qPuzOEfcm46zwVnqskB2yTSNAp8YrItWbT9L1iHm/Hzkw7IYd5yhSZVIDCkdTg\nX2Buifc++SDIurDGwUbHmgGkqJwgYglaU2HfBe5rzGTXKQ6bOZeWpuVvm11j1bU9\ncVyWvDmj9wY9un+C2FEeFpGfuQn5VEmcovuR1jRmu5vr2cvCpEj6tQAO9IGOCl3s\n0skaSmb9bSd91rftpblmZcjcBV6oKQK7Uag0BQIDAQABoF0wWwYJKoZIhvcNAQkO\nMU4wTDBKBgNVHREEQzBBgj9hbS0xLmFtLWVuZHBvaW50cy50ZXN0LXByb21ldGhl\ndXMtYWxlcnRzLTMyazQuc3ZjLmNsdXN0ZXIubG9jYWwwDQYJKoZIhvcNAQELBQAD\nggEBAI66l+73jTigQvvUNs/cfWGQIPj18ED6pXWZcBjrUGueM47JXBP8hvZx5JuY\nw/myI90LPZMV/z7HZVJtadv9mpF3mefEtY5ul1liO4PG/47iQnyQmzI61revsUex\nqiCOB6WChdxdoBmHhGaL7VnWBajHZ+QL+I1Xo0hYdcwNE+vJqTKXwy6cI9bNNkVV\nIpxOjL+AYUn5qt3s1qkYAkCZvSmNswwlh5gSFAEBrO8fUtEj9i1Fwo8iq4HbJ6vZ\n1RWFaNDwNjgZ09TGm47xBk39XD9UpdOrBBYEvG4NOljmSeFBy3OeDZ/phzBLOsuc\nB19EN9zx6B6uqV7Io2s0nSbtD9Y=\n-----END CERTIFICATE REQUEST-----" not found


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 269, in get_secret
    content = self._backend.secret_get(id=id, label=label)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 3052, in secret_get
    raise SecretNotFoundError() from e
ops.model.SecretNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 2693, in _run
    result = subprocess.run(args, **kwargs)  # type: ignore
  File "/usr/lib/python3.8/subprocess.py", line 516, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('/var/lib/juju/tools/unit-am-1/secret-info-get', '--label', 'afd8c2bccf834997afce12c2706d2ede------BEGIN CERTIFICATE REQUEST-----\nMIIC4DCCAcgCAQAwPjENMAsGA1UEAwwEYW0vMTEtMCsGA1UELQwkZmJlYmZkMmMt\nMWE4My00ZDU5LWFiYmYtYzEyNzhlNThmNzc1MIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEAr/1OM2Jdh8IpqhA74xvsFOJZhel6nkJMVkO3zPtX8Ghz65z1\nl4bmoP2bkwEOI1n9tyEmzObHKh30KmnMMGby/1FVOd9MlQ5+jnF3uO5yTcDdO721\n+4qPuzOEfcm46zwVnqskB2yTSNAp8YrItWbT9L1iHm/Hzkw7IYd5yhSZVIDCkdTg\nX2Buifc++SDIurDGwUbHmgGkqJwgYglaU2HfBe5rzGTXKQ6bOZeWpuVvm11j1bU9\ncVyWvDmj9wY9un+C2FEeFpGfuQn5VEmcovuR1jRmu5vr2cvCpEj6tQAO9IGOCl3s\n0skaSmb9bSd91rftpblmZcjcBV6oKQK7Uag0BQIDAQABoF0wWwYJKoZIhvcNAQkO\nMU4wTDBKBgNVHREEQzBBgj9hbS0xLmFtLWVuZHBvaW50cy50ZXN0LXByb21ldGhl\ndXMtYWxlcnRzLTMyazQuc3ZjLmNsdXN0ZXIubG9jYWwwDQYJKoZIhvcNAQELBQAD\nggEBAI66l+73jTigQvvUNs/cfWGQIPj18ED6pXWZcBjrUGueM47JXBP8hvZx5JuY\nw/myI90LPZMV/z7HZVJtadv9mpF3mefEtY5ul1liO4PG/47iQnyQmzI61revsUex\nqiCOB6WChdxdoBmHhGaL7VnWBajHZ+QL+I1Xo0hYdcwNE+vJqTKXwy6cI9bNNkVV\nIpxOjL+AYUn5qt3s1qkYAkCZvSmNswwlh5gSFAEBrO8fUtEj9i1Fwo8iq4HbJ6vZ\n1RWFaNDwNjgZ09TGm47xBk39XD9UpdOrBBYEvG4NOljmSeFBy3OeDZ/phzBLOsuc\nB19EN9zx6B6uqV7Io2s0nSbtD9Y=\n-----END CERTIFICATE REQUEST-----', '--format=json')' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 3059, in _run_for_secret
    return self._run(*args, return_output=return_output, use_json=use_json)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 2695, in _run
    raise ModelError(e.stderr)
ops.model.ModelError: ERROR secret "afd8c2bccf834997afce12c2706d2ede------BEGIN CERTIFICATE REQUEST-----\nMIIC4DCCAcgCAQAwPjENMAsGA1UEAwwEYW0vMTEtMCsGA1UELQwkZmJlYmZkMmMt\nMWE4My00ZDU5LWFiYmYtYzEyNzhlNThmNzc1MIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEAr/1OM2Jdh8IpqhA74xvsFOJZhel6nkJMVkO3zPtX8Ghz65z1\nl4bmoP2bkwEOI1n9tyEmzObHKh30KmnMMGby/1FVOd9MlQ5+jnF3uO5yTcDdO721\n+4qPuzOEfcm46zwVnqskB2yTSNAp8YrItWbT9L1iHm/Hzkw7IYd5yhSZVIDCkdTg\nX2Buifc++SDIurDGwUbHmgGkqJwgYglaU2HfBe5rzGTXKQ6bOZeWpuVvm11j1bU9\ncVyWvDmj9wY9un+C2FEeFpGfuQn5VEmcovuR1jRmu5vr2cvCpEj6tQAO9IGOCl3s\n0skaSmb9bSd91rftpblmZcjcBV6oKQK7Uag0BQIDAQABoF0wWwYJKoZIhvcNAQkO\nMU4wTDBKBgNVHREEQzBBgj9hbS0xLmFtLWVuZHBvaW50cy50ZXN0LXByb21ldGhl\ndXMtYWxlcnRzLTMyazQuc3ZjLmNsdXN0ZXIubG9jYWwwDQYJKoZIhvcNAQELBQAD\nggEBAI66l+73jTigQvvUNs/cfWGQIPj18ED6pXWZcBjrUGueM47JXBP8hvZx5JuY\nw/myI90LPZMV/z7HZVJtadv9mpF3mefEtY5ul1liO4PG/47iQnyQmzI61revsUex\nqiCOB6WChdxdoBmHhGaL7VnWBajHZ+QL+I1Xo0hYdcwNE+vJqTKXwy6cI9bNNkVV\nIpxOjL+AYUn5qt3s1qkYAkCZvSmNswwlh5gSFAEBrO8fUtEj9i1Fwo8iq4HbJ6vZ\n1RWFaNDwNjgZ09TGm47xBk39XD9UpdOrBBYEvG4NOljmSeFBy3OeDZ/phzBLOsuc\nB19EN9zx6B6uqV7Io2s0nSbtD9Y=\n-----END CERTIFICATE REQUEST-----" not found


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-am-1/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 1355, in _on_relation_changed
    secret = self.model.get_secret(
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 274, in get_secret
    info = self._backend.secret_info_get(id=id, label=label)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 3073, in secret_info_get
    result = self._run_for_secret('secret-info-get', *args, return_output=True, use_json=True)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 3062, in _run_for_secret
    raise SecretNotFoundError() from e
ops.model.SecretNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 2693, in _run
    result = subprocess.run(args, **kwargs)  # type: ignore
  File "/usr/lib/python3.8/subprocess.py", line 516, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('/var/lib/juju/tools/unit-am-1/secret-add', '--label', 'afd8c2bccf834997afce12c2706d2ede------BEGIN CERTIFICATE REQUEST-----\nMIIC4DCCAcgCAQAwPjENMAsGA1UEAwwEYW0vMTEtMCsGA1UELQwkZmJlYmZkMmMt\nMWE4My00ZDU5LWFiYmYtYzEyNzhlNThmNzc1MIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEAr/1OM2Jdh8IpqhA74xvsFOJZhel6nkJMVkO3zPtX8Ghz65z1\nl4bmoP2bkwEOI1n9tyEmzObHKh30KmnMMGby/1FVOd9MlQ5+jnF3uO5yTcDdO721\n+4qPuzOEfcm46zwVnqskB2yTSNAp8YrItWbT9L1iHm/Hzkw7IYd5yhSZVIDCkdTg\nX2Buifc++SDIurDGwUbHmgGkqJwgYglaU2HfBe5rzGTXKQ6bOZeWpuVvm11j1bU9\ncVyWvDmj9wY9un+C2FEeFpGfuQn5VEmcovuR1jRmu5vr2cvCpEj6tQAO9IGOCl3s\n0skaSmb9bSd91rftpblmZcjcBV6oKQK7Uag0BQIDAQABoF0wWwYJKoZIhvcNAQkO\nMU4wTDBKBgNVHREEQzBBgj9hbS0xLmFtLWVuZHBvaW50cy50ZXN0LXByb21ldGhl\ndXMtYWxlcnRzLTMyazQuc3ZjLmNsdXN0ZXIubG9jYWwwDQYJKoZIhvcNAQELBQAD\nggEBAI66l+73jTigQvvUNs/cfWGQIPj18ED6pXWZcBjrUGueM47JXBP8hvZx5JuY\nw/myI90LPZMV/z7HZVJtadv9mpF3mefEtY5ul1liO4PG/47iQnyQmzI61revsUex\nqiCOB6WChdxdoBmHhGaL7VnWBajHZ+QL+I1Xo0hYdcwNE+vJqTKXwy6cI9bNNkVV\nIpxOjL+AYUn5qt3s1qkYAkCZvSmNswwlh5gSFAEBrO8fUtEj9i1Fwo8iq4HbJ6vZ\n1RWFaNDwNjgZ09TGm47xBk39XD9UpdOrBBYEvG4NOljmSeFBy3OeDZ/phzBLOsuc\nB19EN9zx6B6uqV7Io2s0nSbtD9Y=\n-----END CERTIFICATE REQUEST-----', '--expire', '2024-07-04T13:13:51', '--owner', 'application', 'certificate=-----BEGIN CERTIFICATE-----\nMIIDUzCCAjugAwIBAgIUf9FNOkfPS0Z82DiyDnuAM+mvwQ4wDQYJKoZIhvcNAQEL\nBQAwOTELMAkGA1UEBhMCVVMxKjAoBgNVBAMMIXNlbGYtc2lnbmVkLWNlcnRpZmlj\nYXRlcy1vcGVyYXRvcjAeFw0yMzA3MTIxMzEzNTFaFw0yNDA3MTExMzEzNTFaMD4x\nDTALBgNVBAMMBGFtLzExLTArBgNVBC0MJGZiZWJmZDJjLTFhODMtNGQ1OS1hYmJm\nLWMxMjc4ZTU4Zjc3NTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK/9\nTjNiXYfCKaoQO+Mb7BTiWYXpep5CTFZDt8z7V/Boc+uc9ZeG5qD9m5MBDiNZ/bch\nJszmxyod9CppzDBm8v9RVTnfTJUOfo5xd7juck3A3Tu9tfuKj7szhH3JuOs8FZ6r\nJAdsk0jQKfGKyLVm0/S9Yh5vx85MOyGHecoUmVSAwpHU4F9gbon3PvkgyLqwxsFG\nx5oBpKicIGIJWlNh3wXua8xk1ykOmzmXlqblb5tdY9W1PXFclrw5o/cGPbp/gthR\nHhaRn7kJ+VRJnKL7kdY0Zrub69nLwqRI+rUADvSBjgpd7NLJGkpm/W0nfda37aW5\nZmXI3AVeqCkCu1GoNAUCAwEAAaNOMEwwSgYDVR0RBEMwQYI/YW0tMS5hbS1lbmRw\nb2ludHMudGVzdC1wcm9tZXRoZXVzLWFsZXJ0cy0zMms0LnN2Yy5jbHVzdGVyLmxv\nY2FsMA0GCSqGSIb3DQEBCwUAA4IBAQCZk53IRkcfmr3rwpT1HjYmwvjWM37VwwY5\no1vfym3N+968kipgLjT9cEOPXchkhjlla7udsmyWeALU71eb37eZGQ7lN/cA4/J4\nuvIQqUfad5a8mk6WK0IVpdbxpbVX2wckFV4ZXYtIS7sHd4QXfy1J69Wjxc/h6U3V\nbefVCvtnco2MhD+Y93Im7sfbtRQvWRxTdinbnv7CXNee+lhVHBFE6TbTbE4xOj2S\nYegeoPOXW+p1D20k6IweANu4GNqJIRST4+xsISFPYs1gdb7z1+5uZ4oU5ElKt3CW\n7PH3oSCrHrx8iXg31/3yP+415tRb5cWotQRFE8Ev8pHz72dBUNx3\n-----END CERTIFICATE-----')' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./src/charm.py", line 542, in <module>
    main(AlertmanagerCharm)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/main.py", line 441, in main
    _emit_charm_event(charm, dispatcher.event_name)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/main.py", line 149, in _emit_charm_event
    event_to_emit.emit(*args, **kwargs)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/framework.py", line 344, in emit
    framework._emit(event)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/framework.py", line 833, in _emit
    self._reemit(event_path)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/framework.py", line 922, in _reemit
    custom_handler(event)
  File "/var/lib/juju/agents/unit-am-1/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 1365, in _on_relation_changed
    secret = self.charm.app.add_secret(
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 427, in add_secret
    id = self._backend.secret_add(
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 3119, in secret_add
    result = self._run('secret-add', *args, return_output=True)
  File "/var/lib/juju/agents/unit-am-1/charm/venv/ops/model.py", line 2695, in _run
    raise ModelError(e.stderr)
ops.model.ModelError: ERROR this unit is not the leader

Documentation recommends `relation-joined` instead of `relation-created`

relation-joined is fired when a remote application is scaled up (i.e. fired for each remote unit that joins the relation)
relation-created is fired once*, when the unit first "learns" about the relation

reference:
https://juju.is/docs/sdk/relation-name-relation-joined-event
https://juju.is/docs/sdk/relation-name-relation-created-event

with that in mind, it seems like this code (which requests a new certificate) should be for relation-created, not relation-joined:

self.on.certificates_relation_joined, self._on_certificates_relation_joined

def _on_certificates_relation_joined(self, event: RelationJoinedEvent) -> None:
replicas_relation = self.model.get_relation("replicas")
if not replicas_relation:
self.unit.status = WaitingStatus("Waiting for peer relation to be created")
event.defer()
return
private_key_password = replicas_relation.data[self.app].get("private_key_password")
private_key = replicas_relation.data[self.app].get("private_key")
csr = generate_csr(
private_key=private_key.encode(),
private_key_password=private_key_password.encode(),
subject=self.cert_subject,
)
replicas_relation.data[self.app].update({"csr": csr.decode()})
self.certificates.request_certificate_creation(certificate_signing_request=csr)

related:
canonical/opensearch-operator#201
canonical/mysql-router-k8s-operator#101

Schema IDs are set incorrectly

I'm assuming these are incorrect, although I'm not sure what the implications are. Perhaps it is just an arbitrary ID anyway so this doesn't matter so much.

"$id": "https://canonical.github.io/charm-relation-interfaces/tls_certificates/v2/schemas/requirer.json", # noqa: E501

"$id": "https://canonical.github.io/charm-relation-interfaces/tls_certificates/v2/schemas/provider.json", # noqa: E501

The schema references (v2) do not exist, only v0 and v1 do, and the URI ins slightly different:

https://canonical.github.io/charm-relation-interfaces/interfaces/tls_certificates/v1/schemas/requirer.json

See https://github.com/canonical/charm-relation-interfaces/tree/main/interfaces/tls_certificates

I assume this was accidentally bumped to v2 when the tls-certificates-interface library was bumped to v2.

Can't relate more than one tls-certificates-operator per relation name.

Issue

Having several tls-certificates-operator charms relating on the same relation name will lead to an error on the requirer side.

A charm that handles more than one relation:

# metadata.yaml on requirer charm
requires:
  trusted-client:
    interface: tls-certificates
    limit: 10

We deploy a couple of tls-certificates-operator charms and name them differently. We would relate by doing:

juju relate kafka:trusted-client tls-one
juju relate kafka:trusted-client tls-two

This leads to the following status:

App         Version  Status  Scale  Charm                      Channel  Rev  Exposed  Message
tls-one              active      1  tls-certificates-operator  edge      22  no       
tls-two              active      1  tls-certificates-operator  edge      22  no       
kafka                error       1  kafka                                 1  no       hook failed: "trusted-client-relation-changed"    

Unit           Workload  Agent  Machine  Public address  Ports  Message
tls-one/0*     active    idle   5        10.47.83.143           
tls-two/0*     active    idle   7        10.47.83.206           
kafka/2*       error     idle   6        10.47.83.190           hook failed: "trusted-client-relation-changed"  

The error on the juju logs shows:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-kafka-3/charm/./src/charm.py", line 476, in <module>
    main(KafkaCharm)
  File "/var/lib/juju/agents/unit-kafka-3/charm/venv/ops/main.py", line 435, in main
    _emit_charm_event(charm, dispatcher.event_name)
  File "/var/lib/juju/agents/unit-kafka-3/charm/venv/ops/main.py", line 144, in _emit_charm_event
    event_to_emit.emit(*args, **kwargs)
  File "/var/lib/juju/agents/unit-kafka-3/charm/venv/ops/framework.py", line 355, in emit
    framework._emit(event)  # noqa
  File "/var/lib/juju/agents/unit-kafka-3/charm/venv/ops/framework.py", line 824, in _emit
    self._reemit(event_path)
  File "/var/lib/juju/agents/unit-kafka-3/charm/venv/ops/framework.py", line 899, in _reemit
    custom_handler(event)
  File "/var/lib/juju/agents/unit-kafka-3/charm/lib/charms/tls_certificates_interface/v1/tls_certificates.py", line 1278, in _on_relation_changed
    relation = self.model.get_relation(self.relationship_name)
  File "/var/lib/juju/agents/unit-kafka-3/charm/venv/ops/model.py", line 249, in get_relation
    return self.relations._get_unique(relation_name, relation_id)
  File "/var/lib/juju/agents/unit-kafka-3/charm/venv/ops/model.py", line 712, in _get_unique
    raise TooManyRelatedAppsError(relation_name, num_related, 1)
ops.model.TooManyRelatedAppsError: Too many remote applications on trusted-clients (2 > 1)

Cause

This happens because tls-certificates-interface calls get_relation() with self.relationship_name:

relation = self.model.get_relation(self.relationship_name)

Since there are two apps using the same relation name, the call fails.

Possible solution

Instead of using self.relationship_name to get the relation, change to using relation_id. See get_relation()

[3.5] AttributeError: 'builtins.Certificate' object has no attribute 'not_valid_after_utc'

Using tls_certificates 3.5 I came across the error indicated in the SUBJECT.

This issue happens if no certficate request is present yet, and a SecretNotFound error is raised when the corresponding secret is to be accessed.

Then an attempt is made to create the request. However at this point the not_valid_after_utc attribute is referred, which is raising the error above.

The issue doesn't happen with 3.0 for sure (I didn't try further versions), I'm glad 3.0 works ๐Ÿ˜…

The full trace goes as below

unit-opensearch-dashboards-2: 09:21:59 ERROR unit.opensearch-dashboards/2.juju-log certificates:6: Uncaught exception while in charm code:
Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/model.py", line 2955, in _run
    result = subprocess.run(args, **kwargs)  # type: ignore
  File "/usr/lib/python3.10/subprocess.py", line 526, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('/var/lib/juju/tools/unit-opensearch-dashboards-2/secret-get', '--label', 'afd8c2bccf834997afce12c2706d2ede------BEGIN CERTIFICATE REQUEST-----\nMIICizCCAXMCAQAwRjEVMBMGA1
UEAwwMMTAuNjcuMTQ3LjE1MS0wKwYDVQQtDCRh\nMjFkYmE2ZC03YjUxLTQxNjctODFmMS0yYTc4ZDYwODYzYmEwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQCaemwCLsCUTttzH1lV6gZh5u/4hS4DT0yiTclN\nq28dKwdoiiNt7DEP0SvymA0kba5fIwa1ETKVHqjm
HMAI3ma3TvQ5pD/rxWrco6Jd\nWx86p5cP2k8iIoyiekenvUgCsv3FefcdQs38l9EJ1pd29gRvF5nHbkXgAaznS0bR\n0qzwoUzfRa/dq31Fj4WO7J4AbItaHsLiBWMApde8J9SLHjZhc/PmS/HWAGlzjH1U\n7c/gfdPitDH56YM8ikQDqGHuiA/zzUNijer7u26P0oJtVxRNQMLpzm
Ln8csdfUV9\nm9NBDymBWnJlI6q6TsR0YzNVqzhrCFI7s7f9EsQizcukVyknAgMBAAGgADANBgkq\nhkiG9w0BAQsFAAOCAQEAUQXlPd6L3P6tHA94HReYBl3zBdAI85Cp1ziA0sVUE+Ik\n/RCl5YP6rJlaMV0nk/e7vou+9OAOAo5mLHZIN5STQ2ghoiuxcS86SJB5P1kIuzbI\nSV
dU99L1otYqLESSSRkMwD0VLnByFxy/FBLHGtN4tslR4lx6Iy44/ZyvUJHOnT6p\nmEUzDZoE5NHwKQ7yuiiVfUYOxScu0Wglk29OjQi/o2Vz4GSVvktVq1G9zCszMZFH\ng2PYA6sz03jD+GCsC470qcDaCeM+3T89YRf6OYA/6AiQ8CuB0h/EvN3I/SvGo723\nNe5MIdfENpCwu2nd
w/XK32nCBXtfu12vDa9+UnAOkg==\n-----END CERTIFICATE REQUEST-----', '--format=json')' returned non-zero exit status 1.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/model.py", line 3311, in secret_get
    result = self._run('secret-get', *args, return_output=True, use_json=True)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/model.py", line 2957, in _run
    raise ModelError(e.stderr) from e
ops.model.ModelError: ERROR consumer label "afd8c2bccf834997afce12c2706d2ede------BEGIN CERTIFICATE REQUEST-----\nMIICizCCAXMCAQAwRjEVMBMGA1UEAwwMMTAuNjcuMTQ3LjE1MS0wKwYDVQQtDCRh\nMjFkYmE2ZC03YjUxLTQxNjctODFmMS0y
YTc4ZDYwODYzYmEwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQCaemwCLsCUTttzH1lV6gZh5u/4hS4DT0yiTclN\nq28dKwdoiiNt7DEP0SvymA0kba5fIwa1ETKVHqjmHMAI3ma3TvQ5pD/rxWrco6Jd\nWx86p5cP2k8iIoyiekenvUgCsv3FefcdQs38l9EJ1pd29g
RvF5nHbkXgAaznS0bR\n0qzwoUzfRa/dq31Fj4WO7J4AbItaHsLiBWMApde8J9SLHjZhc/PmS/HWAGlzjH1U\n7c/gfdPitDH56YM8ikQDqGHuiA/zzUNijer7u26P0oJtVxRNQMLpzmLn8csdfUV9\nm9NBDymBWnJlI6q6TsR0YzNVqzhrCFI7s7f9EsQizcukVyknAgMBAAGgADAN
Bgkq\nhkiG9w0BAQsFAAOCAQEAUQXlPd6L3P6tHA94HReYBl3zBdAI85Cp1ziA0sVUE+Ik\n/RCl5YP6rJlaMV0nk/e7vou+9OAOAo5mLHZIN5STQ2ghoiuxcS86SJB5P1kIuzbI\nSVdU99L1otYqLESSSRkMwD0VLnByFxy/FBLHGtN4tslR4lx6Iy44/ZyvUJHOnT6p\nmEUzDZoE
5NHwKQ7yuiiVfUYOxScu0Wglk29OjQi/o2Vz4GSVvktVq1G9zCszMZFH\ng2PYA6sz03jD+GCsC470qcDaCeM+3T89YRf6OYA/6AiQ8CuB0h/EvN3I/SvGo723\nNe5MIdfENpCwu2ndw/XK32nCBXtfu12vDa9+UnAOkg==\n-----END CERTIFICATE REQUEST-----" not fou
nd


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/lib/charms/tls_certificates_interface/v3/tls_certificates.py", line 1777, in _on_relation_changed
    secret = self.model.get_secret(label=f"{LIBID}-{certificate.csr}")
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/model.py", line 276, in get_secret
    content = self._backend.secret_get(id=id, label=label)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/model.py", line 3314, in secret_get
    raise SecretNotFoundError() from e
ops.model.SecretNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/./src/charm.py", line 265, in <module>
    main(OpensearchDasboardsCharm)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/main.py", line 436, in main
    _emit_charm_event(charm, dispatcher.event_name)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/main.py", line 144, in _emit_charm_event
    event_to_emit.emit(*args, **kwargs)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/framework.py", line 351, in emit
    framework._emit(event)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/framework.py", line 853, in _emit
    self._reemit(event_path)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/venv/ops/framework.py", line 942, in _reemit
    custom_handler(event)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/lib/charms/tls_certificates_interface/v3/tls_certificates.py", line 1786, in _on_relation_changed
    expire=self._get_next_secret_expiry_time(certificate.certificate),
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/lib/charms/tls_certificates_interface/v3/tls_certificates.py", line 1809, in _get_next_secret_expiry_time
    expiry_time = _get_certificate_expiry_time(certificate)
  File "/var/lib/juju/agents/unit-opensearch-dashboards-2/charm/lib/charms/tls_certificates_interface/v3/tls_certificates.py", line 684, in _get_certificate_expiry_time
    return certificate_object.not_valid_after_utc
AttributeError: 'builtins.Certificate' object has no attribute 'not_valid_after_utc'

ops.model.ModelError: ERROR permission denied

Bug Description

Failure hook failed: "certificates-relation-changed"

To Reproduce

See all details on https://github.com/canonical/opensearch-dashboards-operator/actions/runs/9905318848/job/27364829899#step:22:280

Environment

See all details on https://github.com/canonical/opensearch-dashboards-operator/actions/runs/9905318848/job/27364829899#step:22:280

Relevant log output

Model  Controller           Cloud/Region         Version  SLA          Timestamp
test   localhost-localhost  localhost/localhost  3.4.3    unsupported  09:18:32Z

App                       Version  Status   Scale  Charm                     Channel        Rev  Exposed  Message
application                        unknown      1  application                                0  no       
opensearch                         error        2  opensearch                2/edge         114  no       hook failed: "certificates-relation-changed"
opensearch-dashboards              blocked      3  opensearch-dashboards                      0  no       Opensearch connection is missing
self-signed-certificates           active       1  self-signed-certificates  latest/stable  155  no       

Unit                         Workload     Agent      Machine  Public address  Ports     Message
application/0*               unknown      idle       3        10.72.72.203              
opensearch-dashboards/0      active       idle       0        10.72.72.9      5601/tcp  
opensearch-dashboards/1*     active       idle       1        10.72.72.68     5601/tcp  
opensearch-dashboards/2      active       idle       2        10.72.72.224    5601/tcp  
opensearch/0                 error        idle       5        10.72.72.249              hook failed: "certificates-relation-changed"
opensearch/1*                maintenance  executing  6        10.72.72.165              Waiting for TLS to be fully configured...
self-signed-certificates/0*  active       executing  4        10.72.72.4                
unit-opensearch-0: 09:18:31 ERROR unit.opensearch/0.juju-log certificates:6: Uncaught exception while in charm code:
Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/model.py", line 3180, in _run
    result = subprocess.run(args, **kwargs)  # type: ignore
  File "/usr/lib/python3.10/subprocess.py", line 526, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('/var/lib/juju/tools/unit-opensearch-0/secret-get', '--label', 'opensearch:app:app-admin', '--format=json')' returned non-zero exit status 1.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-opensearch-0/charm/./src/charm.py", line 213, in <module>
    main(OpenSearchOperatorCharm)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/main.py", line 548, in main
    manager.run()
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/main.py", line 527, in run
    self._emit()
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/main.py", line 516, in _emit
    _emit_charm_event(self.charm, self.dispatcher.event_name)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/main.py", line 147, in _emit_charm_event
    event_to_emit.emit(*args, **kwargs)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/framework.py", line 348, in emit
    framework._emit(event)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/framework.py", line 860, in _emit
    self._reemit(event_path)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/framework.py", line 950, in _reemit
    custom_handler(event)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/lib/charms/tls_certificates_interface/v3/tls_certificates.py", line 1811, in _on_relation_changed
    self.on.certificate_available.emit(
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/framework.py", line 348, in emit
    framework._emit(event)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/framework.py", line 860, in _emit
    self._reemit(event_path)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/framework.py", line 950, in _reemit
    custom_handler(event)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/lib/charms/opensearch/v0/opensearch_tls.py", line 209, in _on_certificate_available
    self.store_new_ca(self.charm.secrets.get_object(scope, cert_type.val))
  File "/var/lib/juju/agents/unit-opensearch-0/charm/lib/charms/opensearch/v0/opensearch_tls.py", line 444, in store_new_ca
    self._create_keystore_pwd_if_not_exists(Scope.APP, CertType.APP_ADMIN, "ca")
  File "/var/lib/juju/agents/unit-opensearch-0/charm/lib/charms/opensearch/v0/opensearch_tls.py", line 427, in _create_keystore_pwd_if_not_exists
    secrets = self.charm.secrets.get_object(scope, cert_type.val)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/lib/charms/opensearch/v0/opensearch_secrets.py", line 331, in get_object
    return self._get_juju_secret_content(scope, key)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/lib/charms/opensearch/v0/opensearch_secrets.py", line 210, in _get_juju_secret_content
    secret = self._get_juju_secret(scope, key)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/lib/charms/opensearch/v0/opensearch_secrets.py", line 198, in _get_juju_secret
    secret = self._charm.model.get_secret(label=label)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/model.py", line 291, in get_secret
    content = self._backend.secret_get(id=id, label=label)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/model.py", line 3545, in secret_get
    result = self._run('secret-get', *args, return_output=True, use_json=True)
  File "/var/lib/juju/agents/unit-opensearch-0/charm/venv/ops/model.py", line 3182, in _run
    raise ModelError(e.stderr) from e
ops.model.ModelError: ERROR permission denied


### Additional context

Clearly the issue is not on the lib's side. However it may be good to protect against it in the lib...

Libjuju version which is used for integration tests does not appropriate for Juju 3.1/stable

Problem:

Libjuju version does not appropriate for Juju 3.1/stable.
If we use Python 3.11 in the host and run integration tests, we get issues with asyncio loop.

Environment:

Juju server: 3.1.6
Python: 3.11
Juju client pinned in tox.ini: 3.0.4

How to reproduce:

Run tox -e integration

Error logs:

__________________________________________________ ERROR at setup of TestIntegration.test_given_enough_time_passed_then_certificate_expired __________________________________________________
Traceback (most recent call last):
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/runner.py", line 341, in from_call
    result: Optional[TResult] = func()
                                ^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/runner.py", line 262, in <lambda>
    lambda: ihook(item=item, **kwds), when=when, reraise=reraise
            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pluggy/_hooks.py", line 493, in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pluggy/_manager.py", line 115, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pluggy/_callers.py", line 152, in _multicall
    return outcome.get_result()
           ^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pluggy/_result.py", line 114, in get_result
    raise exc.with_traceback(exc.__traceback__)
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/runner.py", line 157, in pytest_runtest_setup
    item.session._setupstate.setup(item)
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/runner.py", line 497, in setup
    raise exc
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/runner.py", line 494, in setup
    col.setup()
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/python.py", line 1795, in setup
    self._request._fillfixtures()
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/fixtures.py", line 566, in _fillfixtures
    item.funcargs[argname] = self.getfixturevalue(argname)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/fixtures.py", line 585, in getfixturevalue
    fixturedef = self._get_active_fixturedef(argname)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/fixtures.py", line 607, in _get_active_fixturedef
    self._compute_fixture_value(fixturedef)
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/fixtures.py", line 693, in _compute_fixture_value
    fixturedef.execute(request=subrequest)
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/fixtures.py", line 1059, in execute
    raise val.with_traceback(tb)
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/fixtures.py", line 1123, in pytest_fixture_setup
    result = call_fixture_func(fixturefunc, request, kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/_pytest/fixtures.py", line 902, in call_fixture_func
    fixture_result = fixturefunc(**kwargs)
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pytest_asyncio/plugin.py", line 304, in _asyncgen_fixture_wrapper
    result = event_loop.run_until_complete(setup())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pytest_asyncio/plugin.py", line 286, in setup
    res = await gen_obj.__anext__()
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pytest_operator/plugin.py", line 231, in ops_test
    await ops_test._setup_model()
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/pytest_operator/plugin.py", line 708, in _setup_model
    await self._controller.connect(self.controller_name)
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/juju/controller.py", line 136, in connect
    await self.update_endpoints()
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/juju/controller.py", line 139, in update_endpoints
    info = await self.info()
           ^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/juju/controller.py", line 283, in info
    return await controller_facade.ControllerAPIInfoForModels(entities=params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/juju/client/facade.py", line 481, in wrapper
    reply = await f(*args, **kwargs)
            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/juju/client/_client11.py", line 650, in ControllerAPIInfoForModels
    reply = await self.rpc(msg)
            ^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/juju/client/facade.py", line 654, in rpc
    result = await self.connection.rpc(msg, encoder=TypeEncoder)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/juju/client/connection.py", line 638, in rpc
    raise errors.JujuAPIError(result)
juju.errors.JujuAPIError: client incompatible with server 3.1.6
Traceback (most recent call last):
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 1337, in close_connection
    await self.close_transport()
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 1355, in close_transport
    if await self.wait_for_connection_lost():
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gatici/telco/tls-certificates-interface/.tox/integration/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 1379, in wait_for_connection_lost
    async with asyncio_timeout(self.close_timeout):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/timeouts.py", line 141, in timeout
    loop = events.get_running_loop()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: no running event loop

Suggested Solution

Use Libjuju 3.2.2

[testenv:integration]
description = Run integration tests
deps =
juju=={env:LIBJUJU_VERSION:3.2.2}

Feature request: Requirers support for requesting all CSR revocation

overview

Currently, it is only possible to request the revocation of a specific certificate using the request_certificate_revocation and specifying the CSR. It would be great to be able to support the revocation of all certificates CSR's without explicitly specifying CSR's.

Usage

certificates = TLSCertificatesRequiresV2(self, "certificates")
certificates.request_all_certificate_revocation()

[v2.1] Need to guard against a relation broken event

When removing an app that was related to self-signed-certificates, the following error is raised:

  File "/var/lib/juju/agents/unit-am-0/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 1366, in _on_relation_broken
    if not relation.data[relation.app].get("certificates"):  # type: ignore[index]
  File "/var/lib/juju/agents/unit-am-0/charm/venv/ops/model.py", line 1346, in __getitem__
    raise KeyError(
KeyError: 'Cannot index relation data with "None". Are you trying to access remote app data during a relation-broken event? This is not allowed.'

Seems like there's a missing guard:

if not relation.app or not relation.app.name:
    # Handle edge case where remote app name can be missing, e.g.,
    # relation_broken events.

Related: canonical/operator#888

Add `auto_renew` kwarg to TLSCertificatesRequiresV1?

I wonder if it would be feasible to add auto-renewal to reduce boilerplate such as _on_certificate_expiring.

self.tls_certificates_requirer = TLSCertificatesRequiresV1(self, "certificates", auto_renew=True)

[v2.6] `permission denied` error when relation joins before leader-elected

I deployed alertmanager and quickly related it to self-signed-certificates.

From the event sequence we can see that relation events for alertmanager fired before leader-elected:

unit-am-0: 21:00:07.168 DEBUG unit.am/0.juju-log Emitting Juju event install.
unit-ca-0: 21:00:07.913 DEBUG unit.ca/0.juju-log certificates:10: Emitting Juju event certificates_relation_joined.
unit-am-0: 21:00:08.042 DEBUG unit.am/0.juju-log certificates:10: Emitting Juju event certificates_relation_created.
unit-ca-0: 21:00:08.303 DEBUG unit.ca/0.juju-log certificates:10: Emitting Juju event certificates_relation_changed.
unit-am-0: 21:00:08.592 DEBUG unit.am/0.juju-log replicas:9: Emitting Juju event replicas_relation_created.
unit-ca-0: 21:00:09.250 DEBUG unit.ca/0.juju-log certificates:10: Emitting Juju event certificates_relation_changed.
unit-ca-0: 21:00:09.259 DEBUG unit.ca/0.juju-log certificates:10: Emitting custom event <CertificateCreationRequestEvent via SelfSignedCertificatesCharm/TLSCertificatesProvidesV2[certificates]/on/certificate_creation_request[107]>.
unit-am-0: 21:00:09.395 DEBUG unit.am/0.juju-log Emitting Juju event leader_elected.

As a result, self-signed-certificates charm is in error state (originating from the tls-certificates library):

unit-ca-0: 21:02:01.919 DEBUG unit.ca/0.juju-log certificates:10: ops 2.4.1 up and running.
unit-ca-0: 21:02:01.939 DEBUG unit.ca/0.juju-log certificates:10: Emitting Juju event certificates_relation_changed.
unit-ca-0: 21:02:01.948 DEBUG unit.ca/0.juju-log certificates:10: Emitting custom event <CertificateCreationRequestEvent via SelfSignedCertificatesCharm/TLSCertificatesProvidesV2[certificates]/on/certificate_creation_request[111]>.
unit-ca-0: 21:02:06.229 INFO unit.ca/0.juju-log certificates:10: Generated certificate for relation 10
unit-ca-0: 21:02:06.247 ERROR unit.ca/0.juju-log certificates:10: Uncaught exception while in charm code:
Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/model.py", line 2693, in _run
    result = subprocess.run(args, **kwargs)  # type: ignore
  File "/usr/lib/python3.10/subprocess.py", line 524, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('/var/lib/juju/tools/unit-ca-0/relation-get', '-r', '6', '-', 'ca', '--app', '--format=json')' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-ca-0/charm/./src/charm.py", line 200, in <module>
    main(SelfSignedCertificatesCharm)
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/main.py", line 441, in main
    _emit_charm_event(charm, dispatcher.event_name)
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/main.py", line 149, in _emit_charm_event
    event_to_emit.emit(*args, **kwargs)
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/framework.py", line 344, in emit
    framework._emit(event)
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/framework.py", line 833, in _emit
    self._reemit(event_path)
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/framework.py", line 922, in _reemit
    custom_handler(event)
  File "/var/lib/juju/agents/unit-ca-0/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 1095, in _on_relation_changed
    self._revoke_certificates_for_which_no_csr_exists(relation_id=event.relation.id)
  File "/var/lib/juju/agents/unit-ca-0/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 1129, in _revoke_certificates_for_which_no_csr_exists
    self.remove_certificate(certificate=certificate["certificate"])
  File "/var/lib/juju/agents/unit-ca-0/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 1054, in remove_certificate
    self._remove_certificate(certificate=certificate, relation_id=certificate_relation.id)
  File "/var/lib/juju/agents/unit-ca-0/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 961, in _remove_certificate
    provider_relation_data = _load_relation_data(relation.data[self.charm.app])
  File "/var/lib/juju/agents/unit-ca-0/charm/lib/charms/tls_certificates_interface/v2/tls_certificates.py", line 597, in _load_relation_data
    for key in raw_relation_data:
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/model.py", line 675, in __iter__
    return iter(self._data)
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/model.py", line 662, in _data
    data = self._lazy_data = self._load()
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/model.py", line 1393, in _load
    return self._backend.relation_get(self.relation.id, self._entity.name, self._is_app)
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/model.py", line 2774, in relation_get
    raw_data_content = self._run(*args, return_output=True, use_json=True)
  File "/var/lib/juju/agents/unit-ca-0/charm/venv/ops/model.py", line 2695, in _run
    raise ModelError(e.stderr)
ops.model.ModelError: ERROR permission denied (unauthorized access)

Use SANs instead of CN by default

The generate_csr util takes a mandatory subject but an optional sans_dns.
This results in certs with deprecated features.

  • Chrome already dropped support for CN
  • Prometheus completely rejects such certs:
        "scrapePool": "prometheus",
        "scrapeUrl": "https://prometheus.local:9090/metrics",
        "globalUrl": "https://prometheus.local:9090/metrics",
        "lastError": "Get \"https://prometheus.local:9090/metrics\": x509: certificate relies on legacy Common Name field, use SANs instead",
        "lastScrape": "2023-06-12T17:08:57.945355854-04:00",
        "lastScrapeDuration": 0.002333149,
        "health": "down",

Moreover, prometheus rejects the cert even if it has both CN and SANs. We should probably drop CN entirely.

It would be handy if the lib generated SANs by default.

Add missing x509 extensions to `generate_certificate`

Problem

The certs generated by the self-signed-certificates operator work fine, but comparing them to certs from e.g. charmhub.io and 1.1.1.1 there a few x509 extensions missing:

  • X509v3 Authority Key Identifier
  • X509v3 Subject Key Identifier
  • X509v3 Key Usage (being impl'd in #72)
  • X509v3 Extended Key Usage
  • X509v3 Certificate Policies
  • X509v3 Basic Constraints (contains "CA:FALSE")

We may not need all of them. For example, openssl verify -x509_strict complains only about one of them:

error 85 at 0 depth lookup: Missing Authority Key Identifier

And openssl s_client -showcerts complains about:

depth=0 CN = 10.43.8.206, x500UniqueIdentifier = 13b9a7cd-7fe3-450d-af31-f64a1a45350d
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = 10.43.8.206, x500UniqueIdentifier = 13b9a7cd-7fe3-450d-af31-f64a1a45350d
verify error:num=21:unable to verify the first certificate
verify return:1
depth=0 CN = 10.43.8.206, x500UniqueIdentifier = 13b9a7cd-7fe3-450d-af31-f64a1a45350d
verify return:1
DONE

Context

I am using the self-signed-certificates operator to sign a bare ip for traefik.
I have the server cert issued by the operator for the bare ip, but curl-ing the ingress url fails with:

*   Trying 10.43.8.206:443...
* Connected to 10.43.8.206 (10.43.8.206) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS header, Unknown (21):
* TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: self-signed certificate
* Closing connection 0
curl: (60) SSL certificate problem: self-signed certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

When I repeat the same but with external_hostname for traefik, then curl-ing trfk.local works fine.

I suspect this may be because some x509 extensions are missing.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

github-actions
.github/workflows/codeql-analysis.yml
  • actions/checkout v4@b4ffde65f46336ab88eb53be808477a3936bae11
  • github/codeql-action v3
  • github/codeql-action v3
  • github/codeql-action v3
.github/workflows/issues.yaml
.github/workflows/lint-pr.yaml
  • amannn/action-semantic-pull-request v5
.github/workflows/main.yml
  • actions/checkout v4@b4ffde65f46336ab88eb53be808477a3936bae11
  • actions/checkout v4@b4ffde65f46336ab88eb53be808477a3936bae11
  • actions/checkout v4@b4ffde65f46336ab88eb53be808477a3936bae11
  • actions/checkout v4
  • actions/upload-artifact v4
  • actions/upload-artifact v4
  • actions/checkout v4
  • actions/upload-artifact v4
  • actions/upload-artifact v4
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
  • ubuntu 22.04
.github/workflows/upload.yml
  • actions/checkout v4@b4ffde65f46336ab88eb53be808477a3936bae11
  • canonical/charming-actions 2.4.0
  • ubuntu 22.04
pip_requirements
requirements.txt
  • ops ==2.9.0
test-requirements.txt
  • black ==23.12.1
  • ops ==2.9.0

  • Check this box to trigger a request for Renovate to run again on this repository

Accept IPv6 address as sans_ip for generate_csr

Bug Description

tls_certificate_interface provides helper functions to generate_csr.
However the function generate_csr accepts only IPv4 Address as sans_ip list but not IPv6 address [1].

[1] https://github.com/canonical/tls-certificates-interface/blob/main/lib/charms/tls_certificates_interface/v3/tls_certificates.py#L1080

To Reproduce

Simple unit test could be easiest way to verify this. I will come back with the unit test.

Environment

Sunbeam currently uses tls_certificates v1.12 but the problem can be observed in v3.15

Relevant log output

See logs from  https://bugs.launchpad.net/sunbeam-charms/+bug/2067481

Additional context

Reference bug observed in sunbeam: https://bugs.launchpad.net/sunbeam-charms/+bug/2067481

Drop the `cryptography` dep for the requirer side

Currently, both the provider and the requirer sides depend on the cryptogrpahy python package.
This results in about 20 min extra packing time for requirer charms.

However, the charm container is ubuntu based and already has openssl, so we could potentially:

  • delegate requrier side crypto logic to openssl via subprocess
  • import cryptography only for the provider

Not sure about entropy though:

  • What kind of randomness (entropy) is available to freshly provisioned charm containers?
  • Does the cryptography package do anything different from openssl with respect to entropy?

Missing custom event for relation removal

I'm integrating the tls-certificates-interface in traefik: canonical/traefik-k8s-operator#100.
When I juju remove-relation between tls-certificates-operator and traefik, the only way to remove the self-signed cert (that came from tls-certificates-operator over relation data) is by manually observing the "relation-broken" event.

Typically we say that a lib is responsible for registering the relation events on behalf of the charm, and emit custom events per need.

Currently the requirer side has these events:

class CertificatesRequirerCharmEvents(CharmEvents):
"""List of events that the TLS Certificates requirer charm can leverage."""
certificate_available = EventSource(CertificateAvailableEvent)
certificate_expiring = EventSource(CertificateExpiringEvent)
certificate_expired = EventSource(CertificateExpiredEvent)
certificate_revoked = EventSource(CertificateRevokedEvent)

none of which is emitted on relation broken.

Ideally I would like to observe a custom event instead of "breaking the pattern" and observe "tls-certificates" relation events directly. Wdyt?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.