+
+
+class Addrs(univ.SequenceOf):
+ componentType = char.PrintableString()
+
+
+class RegistrationInfo(univ.Sequence):
+ """
+ ASN.1 representation of:
+
+ type RegistrationInfo struct {
+ User string
+
+ Addrs []string
+
+ SecretKey []byte
+
+ ControllerName string
+ }
+ """
+ pass
+
+
+def generate_user_controller_access_token(username, controller_endpoints, secret_key, controller_name):
+ """" Implement in python what is currently done in GO
+ https://github.com/juju/juju/blob/a5ab92ec9b7f5da3678d9ac603fe52d45af24412/cmd/juju/user/utils.go#L16
+
+ :param username: name of the user to register
+ :param controller_endpoints: juju controller endpoints list in the format <ip>:<port>
+ :param secret_key: base64 encoded string of the secret-key generated by juju
+ :param controller_name: name of the controller to register to.
+ """
+
+ # Secret key is returned as base64 encoded string in:
+ # https://websockets.readthedocs.io/en/stable/_modules/websockets/protocol.html#WebSocketCommonProtocol.recv
+ # Deconding it before marshalling into the ASN.1 message
+ secret_key = base64.b64decode(secret_key)
+ addr = Addrs()
+ for endpoint in controller_endpoints:
+ addr.append(endpoint)
+
+ registration_string = RegistrationInfo()
+ registration_string.setComponentByPosition(0, char.PrintableString(username))
+ registration_string.setComponentByPosition(1, addr)
+ registration_string.setComponentByPosition(2, univ.OctetString(secret_key))
+ registration_string.setComponentByPosition(3, char.PrintableString(controller_name))
+ registration_string = encode(registration_string)
+ remainder = len(registration_string) % 3
+ registration_string += b"\0" * (3 - remainder)
+ return base64.urlsafe_b64encode(registration_string)