Esempio n. 1
0
def test_docker_pull_config_secret():
    pull_config_str = '{"auths":{"example.com":{"username":"******","password":"******",'\
                      '"email":"*****@*****.**","auth":"f00BA7"}}}'

    migrated_dcos_secret = V1Secret(
        kind='Secret',
        api_version='v1',
        metadata=V1ObjectMeta(name='nothing-depends-on-this-name'),
        data={'nothing-depends-on-the-name-of-this-key': pull_config_str})

    input_manifest_list = ManifestList()
    input_manifest_list.append(
        Manifest(pluginName="secret",
                 manifestName="foo.docker-c_nfig",
                 data=[migrated_dcos_secret]))

    app = {
        "id": "/foo/barify",
        "container": {
            "docker": {
                "pullConfig": {
                    "secret": "pull-config"
                }
            }
        },
        "env": {
            "BAR": {
                "secret": "pull-config"
            }
        },  # See the NOTE below
        "secrets": {
            "pull-config": {
                "source": "/foo/docker-c@nfig"
            },
            "unused": {
                "source": "unused"
            },
        },
    }

    migrator = MarathonMigrator(object=app, manifest_list=input_manifest_list)
    manifest = migrator.migrate()

    # NOTE: Thit test expects that two secrets will be created:
    # one for the image pull config and another for everything else.
    # This might be not the optimal migration startegy.
    [deployment] = [m for m in manifest if isinstance(m, V1Deployment)]

    [pull_secret] = [m for m in manifest \
        if isinstance(m, V1Secret) and m.type == "kubernetes.io/dockerconfigjson"]

    [generic_secret] = [m for m in manifest \
        if isinstance(m, V1Secret) and m.type != "kubernetes.io/dockerconfigjson"]

    assert deployment.spec.template.spec.image_pull_secrets[
        0].name == pull_secret.metadata.name

    assert pull_secret.data[".dockerconfigjson"] == pull_config_str

    assert generic_secret.data["foo.docker-c_nfig"] == pull_config_str
Esempio n. 2
0
    def migrate(self, backupList: BackupList, manifestList: ManifestList,
                **kwargs: Any) -> ManifestList:
        ml = ManifestList()

        for ba in backupList.backups(pluginName='secret'):
            assert isinstance(ba, Backup)
            metadata = V1ObjectMeta()
            metadata.annotations = {}

            clusterMeta = manifestList.clusterMeta()
            if clusterMeta:
                metadata.annotations = clusterMeta.annotations

            logging.debug("Found backup {}".format(ba))
            b = ba.data
            fullPath = "/".join(filter(None, [b["path"], b["key"]]))
            name = b["key"]

            metadata.annotations[utils.namespace_path(
                "secret-path")] = fullPath
            metadata.name = utils.make_subdomain(name.split('/'))
            sec = V1Secret(metadata=metadata)
            sec.api_version = 'v1'
            sec.kind = 'Secret'
            # K8s requires secret values to be base64-encoded.  The secret value
            # is base64-encoded during backup so it can be passed as-is here.
            sec.data = {utils.dnsify(name): b['value']}

            manifest = Manifest(pluginName=self.plugin_name,
                                manifestName=utils.dnsify(fullPath))
            manifest.append(sec)

            ml.append(manifest)

        return ml
Esempio n. 3
0
def _create_remapped_secret(
    manifest_list: Optional[ManifestList],
    remapping: SecretRemapping,
    app_id: str,
) -> Optional[V1Secret]:

    if not remapping.key_mapping:
        return None

    assert manifest_list is not None
    clusterMeta: Optional[V1ObjectMeta] = manifest_list.clusterMeta()

    metadata = V1ObjectMeta(annotations={})
    if clusterMeta is not None:
        metadata.annotations = clusterMeta.annotations

    metadata.annotations[utils.namespace_path("marathon-appid")] = app_id
    metadata.name = utils.dnsify(remapping.dest_name)
    secret = V1Secret(metadata=metadata, data={})
    secret.api_version = 'v1'
    secret.kind = 'Secret'
    if remapping.dest_type is not None:
        secret.type = remapping.dest_type

    for source_key, destination_key in remapping.key_mapping.items():
        sourceSecret = manifest_list.manifest(pluginName='secret', manifestName=source_key)
        if not sourceSecret:
            raise NoMigratedSecretFound('No migrated secret "{}" found'.format(source_key))

        [value] = sourceSecret[0].data.values()
        secret.data[destination_key] = value

    return secret
def make_secret(
    name,
    username,
    cert_paths,
    hub_ca,
    owner_references,
    labels=None,
    annotations=None,
):
    """
    Make a k8s secret specification using pre-existing ssl credentials for a given user.

    Parameters
    ----------
    name:
        Name of the secret. Must be unique within the namespace the object is
        going to be created in.
    username:
        The name of the user notebook.
    cert_paths:
        JupyterHub spawners cert_paths dictionary container certificate path references
    hub_ca:
        Path to the hub certificate authority
    labels:
        Labels to add to the secret.
    annotations:
        Annotations to add to the secret.
    """

    secret = V1Secret()
    secret.kind = "Secret"
    secret.api_version = "v1"
    secret.metadata = V1ObjectMeta()
    secret.metadata.name = name
    secret.metadata.annotations = (annotations or {}).copy()
    secret.metadata.labels = (labels or {}).copy()
    secret.metadata.owner_references = owner_references

    secret.data = {}

    with open(cert_paths['keyfile'], 'r') as file:
        encoded = base64.b64encode(file.read().encode("utf-8"))
        secret.data['ssl.key'] = encoded.decode("utf-8")

    with open(cert_paths['certfile'], 'r') as file:
        encoded = base64.b64encode(file.read().encode("utf-8"))
        secret.data['ssl.crt'] = encoded.decode("utf-8")

    with open(cert_paths['cafile'], 'r') as file:
        encoded = base64.b64encode(file.read().encode("utf-8"))
        secret.data["notebooks-ca_trust.crt"] = encoded.decode("utf-8")

    with open(hub_ca, 'r') as file:
        encoded = base64.b64encode(file.read().encode("utf-8"))
        secret.data["notebooks-ca_trust.crt"] = secret.data[
            "notebooks-ca_trust.crt"
        ] + encoded.decode("utf-8")

    return secret
Esempio n. 5
0
def mocked_k8s_CoreV1Api(mocker):
    mocked_coreV1Api_class = mocker.patch('kubernetes.client.CoreV1Api')
    mocker.patch('kubernetes.client.ApiClient')
    coreV1API_instance = mocked_coreV1Api_class.return_value

    pods_mock = MagicMock()
    pods_mock.items = [
        MagicMock(spec=V1Pod),
        MagicMock(spec=V1Pod),
        MagicMock(spec=V1Pod)
    ]
    coreV1API_instance.list_pod_for_all_namespaces.return_value = pods_mock

    services_mock = MagicMock()
    services_mock.items = [
        MagicMock(spec=V1Service),
        MagicMock(spec=V1Service),
        MagicMock(spec=V1Service)
    ]
    coreV1API_instance.list_service_for_all_namespaces.return_value = services_mock

    v1_namespace = V1Namespace()
    v1_metadata_namespace = V1ObjectMeta(name=test_namespace)
    v1_namespace.metadata = v1_metadata_namespace
    v1_namespace_status = V1NamespaceStatus(phase=NamespaceStatus.ACTIVE.value)
    v1_namespace.status = v1_namespace_status

    coreV1API_instance.read_namespace.return_value = v1_namespace
    coreV1API_instance.delete_namespace.return_value = V1Status(
        status="{'phase': 'Terminating'}")

    v1_config_map = V1ConfigMap(data=test_config_map_data())

    coreV1API_instance.read_namespaced_config_map.return_value = v1_config_map

    secret_data = {"token": TEST_TOKEN}
    v1_metadata_secret = V1ObjectMeta(name="default-token")
    v1_secret = V1Secret(metadata=v1_metadata_secret, data=secret_data)
    v1_secret_list = V1SecretList(items=[v1_secret])

    coreV1API_instance.list_namespaced_secret.return_value = v1_secret_list

    v1_pod_status = V1PodStatus(phase=K8S_RUNNING_POD_STATUS)
    v1_pod = V1Pod(status=v1_pod_status)
    v1_pod_lists = V1PodList(items=[v1_pod])

    coreV1API_instance.list_namespaced_pod.return_value = v1_pod_lists

    v1_metadata_event = V1ObjectMeta(name="default-name")
    v1_object = V1ObjectReference(name="pod_name")
    v1_event = V1Event(message="Insufficient cpu",
                       involved_object=v1_object,
                       metadata=v1_metadata_event)
    v1_event_list = V1EventList(items=[v1_event])

    coreV1API_instance.list_namespaced_event.return_value = v1_event_list

    return coreV1API_instance
def create_example_list_manifest(dir: str) -> ManifestList:
    list = ManifestList(path=str(dir))

    p = "testPlugin"
    b = "foobar"
    metadata = V1ObjectMeta(name="secret1")
    sec = V1Secret(metadata=metadata, kind="Secret", api_version="v1")
    sec.data = {"secret1": "Zm9vYmFy"}
    d = [sec]
    list.append(Manifest(pluginName=p, manifestName=b, data=d))

    list.store()
    return list, p, b, d
Esempio n. 7
0
 def generate_drive_config(self, url, username, token, **kwargs):
     base = DEFAULT_DRIVE_CONFIG.copy()
     base.update(**kwargs)
     cp = configparser.ConfigParser()
     cp.read_dict(base)
     cp['account'].update(dict(server=url, username=username, token=token))
     cfg = io.StringIO()
     cp.write(cfg)
     cfg.seek(0)
     data = {'seadrive.conf': cfg.read()}
     metadata = V1ObjectMeta(
         name='seadrive-{username}-conf'.format(username=username),
         annotations={'username': username})
     secret = V1Secret(string_data=data, metadata=metadata)
     return secret
Esempio n. 8
0
    def make_secret_spec(self):
        name = "dask-gateway-tls-%s" % self.cluster_name
        labels = self.get_labels_for("dask-gateway-tls")
        annotations = self.common_annotations

        secret = V1Secret(
            kind="Secret",
            api_version="v1",
            string_data={
                "dask.crt": self.tls_cert.decode(),
                "dask.pem": self.tls_key.decode(),
            },
            metadata=V1ObjectMeta(name=name,
                                  labels=labels,
                                  annotations=annotations),
        )
        return secret
def test_manifest_comments_deserialization():
    @with_comment
    class V1beta1CronJobWithComment(V1beta1CronJob):
        pass

    obj_with_comment = V1beta1CronJobWithComment(api_version='v999', kind='CronJob')
    obj_with_comment.set_comment([
        "Lorem ipsum dolor sit amet,",
        "consectetur\n adipiscing\n  elit",
    ])

    obj_without_comment = V1Secret(api_version='v678', kind='Secret')

    # No stray newlines should be dumped if the comment is empty.
    obj_with_empty_comment = V1beta1CronJobWithComment(api_version='v1234', kind='CronJob')
    obj_with_empty_comment.set_comment([])

    manifest = Manifest(pluginName='foo',
                        manifestName='bar',
                        data=[obj_with_comment, obj_without_comment, obj_with_empty_comment])

    dump = manifest.dumps(None)
    assert dump == textwrap.dedent("""\
        ---
        # Lorem ipsum dolor sit amet,
        # consectetur
        #  adipiscing
        #   elit
        apiVersion: v999
        kind: CronJob

        ---
        apiVersion: v678
        kind: Secret

        ---
        apiVersion: v1234
        kind: CronJob
    """)
Esempio n. 10
0
def create_manifest_list_cluster() -> ManifestList:
    clusterID = "test-1234-test-test"
    ml = ManifestList()
    metadata = V1ObjectMeta(name="dcos-{}".format(clusterID))
    metadata.annotations = {
        "migration.dcos.d2iq.com/cluster-id": clusterID,
        "migration.dcos.d2iq.com/cluster-name": "testcluster",
        "migration.dcos.d2iq.com/backup-date": "2021-01-25",
    }
    cfgmap = V1ConfigMap(metadata=metadata)
    # models do not set defaults -.-
    cfgmap.kind = "ConfigMap"
    cfgmap.api_version = "v1"
    cfgmap.data = {
        "MESOS_MASTER_STATE_SUMMARY_BASE64":
        b64encode(json.dumps({
            "foo": "bar"
        }).encode("ascii"))
    }

    manifest = Manifest(pluginName="cluster", manifestName="dcos-cluster")
    manifest.append(cfgmap)

    ml.append(manifest)

    secret = Manifest(pluginName="secret", manifestName="hello-world.secret")

    sec = V1Secret(metadata=V1ObjectMeta(name="hello-world.secret",
                                         annotations=metadata.annotations))
    sec.api_version = 'v1'
    sec.kind = 'Secret'
    sec.data = {"hello-world.secret": "Zm9vYmFy"}

    secret.append(sec)

    ml.append(secret)

    return ml
Esempio n. 11
0
    def generate(self, user_id, access_token, refresh_token, user_project_id,
                 project_id):
        self.info("GenIdentity U=%s, P=%s" % (user_id, user_project_id))

        pki_role = "pki-backend-role-%s" % project_id
        jwt_role = "sae-issue-cert-%s" % project_id

        access_token, vault_token = self.vault_login(os.environ['VAULT_ADDR'],
                                                     jwt_role, access_token,
                                                     refresh_token, 1)

        url = "%s/v1/pki_int/issue/%s" % (os.environ['VAULT_ADDR'], pki_role)

        self.info("issue url %s" % url)

        payload = {'common_name': user_project_id}

        headers = {'X-Vault-Token': vault_token}

        x = requests.post(url, data=json.dumps(payload), headers=headers)
        self.info("status_code %s" % x.status_code)
        if x.status_code != 200:
            self.info("text %s" % x.text)
            raise Exception("Failed to issue certificate")
        j = x.json()
        self.info("issue_cert SERIAL NUMBER " + j['data']['serial_number'])

        dirpath = tempfile.mkdtemp()
        self.info("Building creds in %s" % dirpath)

        f = open("%s/crt" % dirpath, "w")
        f.write(j['data']['certificate'])
        f.close()

        f = open("%s/key" % dirpath, "w")
        f.write(j['data']['private_key'])
        f.close()

        os.system(
            "(cd %s; openssl pkcs12 -export -out private.pfx -inkey key -in crt -password pass:password)"
            % dirpath)

        os.system(
            'mkdir %s/nssdb && certutil -d %s/nssdb -N --empty-password' %
            (dirpath, dirpath))
        print("Created new DB")
        os.system(
            'pk12util -v -d sql:%s/nssdb -K password -W password -i %s/private.pfx'
            % (dirpath, dirpath))
        print("Added private key")

        #os.system('echo "password" > pass')
        os.system(
            'certutil -A -n "ca-vaultpki-root" -t TC -i /cacerts/ca-vaultpki-root.crt -d sql:%s/nssdb'
            % dirpath)
        os.system(
            'certutil -A -n "ca-vaultpki-inter" -t TC -i /cacerts/ca-vaultpki-inter.crt -d sql:%s/nssdb'
            % dirpath)
        os.system('certutil -L -d sql:%s/nssdb' % dirpath)

        os.system('ls -la %s/nssdb' % dirpath)

        secret_data = {}
        secret_data['refresh_token'] = base64.b64encode(
            refresh_token.encode('utf-8')).decode('utf-8')
        secret_data['postgresql.crt'] = base64.b64encode(
            j['data']['certificate'].encode('utf-8')).decode('utf-8')
        secret_data['postgresql.key'] = base64.b64encode(
            j['data']['private_key'].encode('utf-8')).decode('utf-8')

        for f in listdir('%s/nssdb' % dirpath):
            data = open("%s/nssdb/%s" % (dirpath, f), "rb").read()
            b64 = base64.b64encode(data)
            secret_data[f] = b64.decode('utf-8')

        self.info("Deleting temp folder %s" % dirpath)
        shutil.rmtree(dirpath)

        namespace = 'vdi'
        metadata = {
            'name': "%s-cert" % user_project_id,
            'namespace': namespace
        }
        secret = V1Secret('v1', secret_data, 'Secret', metadata, type='Opaque')
        print("Secret name = %s" % secret.metadata['name'])
        print(secret_data.keys())
        return secret