def test_create_secret(user_secrets, no_db_user): """Test creation of user secrets.""" corev1_api_client = Mock() corev1_api_client.read_namespaced_secret = Mock( side_effect=ApiException(reason="Secret does not exist.", status=404)) with patch("reana_commons.k8s.secrets." "current_k8s_corev1_api_client", corev1_api_client): secrets_store = REANAUserSecretsStore(no_db_user.id_) secrets_store.add_secrets(user_secrets) corev1_api_client.create_namespaced_secret.assert_called_once() corev1_api_client.replace_namespaced_secret.assert_called_once()
def test_overwrite_secret(corev1_api_client_with_user_secrets, user_secrets, no_db_user): """Test overwriting secrets.""" with patch( "reana_commons.k8s.secrets." "current_k8s_corev1_api_client", corev1_api_client_with_user_secrets(user_secrets), ) as api_client: secrets_store = REANAUserSecretsStore(no_db_user.id_) secrets_store.add_secrets(user_secrets, overwrite=True) api_client.replace_namespaced_secret.assert_called()
def test_create_existing_secrets_fail(corev1_api_client_with_user_secrets, user_secrets, no_db_user): """Test create secrets which already exist without overwrite.""" with patch( "reana_commons.k8s.secrets." "current_k8s_corev1_api_client", corev1_api_client_with_user_secrets(user_secrets), ) as api_client: secrets_store = REANAUserSecretsStore(no_db_user) with pytest.raises(REANASecretAlreadyExists): secrets_store.add_secrets(user_secrets) api_client.replace_namespaced_secret.assert_not_called()
def test_overwrite_secret(corev1_api_client_with_user_secrets, user_secrets, test_user): """Test overwriting secrets.""" with patch('reana_commons.k8s.secrets.' 'current_k8s_corev1_api_client', corev1_api_client_with_user_secrets): secrets_store = REANAUserSecretsStore(test_user) secrets_list = secrets_store.add_secrets(user_secrets, overwrite=True) corev1_api_client_with_user_secrets. \ replace_namespaced_secret.assert_called()
def add_secrets(): # noqa r"""Endpoint to create user secrets. --- post: summary: Add user secrets to REANA. description: >- This resource adds secrets for the authenticated user. operationId: add_secrets produces: - application/json parameters: - name: access_token in: query description: Secrets owner access token. required: false type: string - name: overwrite in: query description: Whether existing secret keys should be overwritten. required: false type: boolean - name: secrets in: body description: >- Optional. List of secrets to be added. required: true schema: type: object additionalProperties: type: object description: Secret definition. properties: name: type: string description: Secret name value: type: string description: Secret value type: type: string enum: - env - file description: >- How will be the secret assigned to the jobs, either exported as an environment variable or mounted as a file. responses: 201: description: >- Secrets successfully added. schema: type: object properties: message: type: string examples: application/json: { "message": "Secret(s) successfully added." } 403: description: >- Request failed. Token is not valid. examples: application/json: { "message": "Token is not valid" } 409: description: >- Request failed. Secrets could not be added due to a conflict. examples: application/json: { "message": "The submitted secrets api_key, password, username already exist." } 500: description: >- Request failed. Internal server error. examples: application/json: { "message": "Internal server error." } """ try: if current_user.is_authenticated: user = _get_user_from_invenio_user(current_user.email) else: user = get_user_from_token(request.args.get('access_token')) secrets_store = REANAUserSecretsStore(str(user.id_)) overwrite = json.loads(request.args.get('overwrite')) secrets_store.add_secrets(request.json, overwrite=overwrite) return jsonify({"message": "Secret(s) successfully added."}), 201 except REANASecretAlreadyExists as e: return jsonify({"message": str(e)}), 409 except ValueError: return jsonify({"message": "Token is not valid."}), 403 except Exception as e: logging.error(traceback.format_exc()) return jsonify({"message": str(e)}), 500
def gitlab_oauth(): # noqa r"""Endpoint to authorize REANA on GitLab. --- get: summary: Get access token from GitLab operationId: gitlab_oauth description: >- Authorize REANA on GitLab. produces: - application/json responses: 200: description: >- Ping succeeded. schema: type: object properties: message: type: string status: type: string examples: application/json: message: OK status: 200 201: description: >- Authorization succeeded. GitLab secret created. schema: type: object properties: message: type: string status: type: string examples: application/json: message: GitLab secret created status: 201 403: description: >- Request failed. User token not valid. examples: application/json: { "message": "Token is not valid." } 500: description: >- Request failed. Internal controller error. """ try: if current_user.is_authenticated: user = _get_user_from_invenio_user(current_user.email) else: user = get_user_from_token(request.args.get("access_token")) if "code" in request.args: # Verifies state parameter and obtain next url state_token = request.args.get("state") assert state_token # Checks authenticity and integrity of state and decodes the value. state = serializer.loads(state_token) # Verifies that state is for this session and that next parameter # has not been modified. assert state["sid"] == _create_identifier() # Stores next URL next_url = state["next"] gitlab_code = request.args.get("code") params = { "client_id": REANA_GITLAB_OAUTH_APP_ID, "client_secret": REANA_GITLAB_OAUTH_APP_SECRET, "redirect_uri": url_for(".gitlab_oauth", _external=True), "code": gitlab_code, "grant_type": "authorization_code", } gitlab_response = requests.post(REANA_GITLAB_URL + "/oauth/token", data=params).content secrets_store = REANAUserSecretsStore(str(user.id_)) secrets_store.add_secrets(_format_gitlab_secrets(gitlab_response), overwrite=True) return redirect(next_url), 201 else: return jsonify({"message": "OK"}), 200 except ValueError: return jsonify({"message": "Token is not valid."}), 403 except (AssertionError, BadData): return jsonify({"message": "State param is invalid."}), 403 except Exception as e: logging.error(traceback.format_exc()) return jsonify({"message": str(e)}), 500
def gitlab_oauth(): # noqa r"""Endpoint to authorize REANA on GitLab. --- get: summary: Get access token from GitLab operationId: gitlab_oauth description: >- Authorize REANA on GitLab. produces: - application/json responses: 200: description: >- Ping succeeded. schema: type: object properties: message: type: string status: type: string examples: application/json: message: OK status: 200 201: description: >- Authorization succeeded. GitLab secret created. schema: type: object properties: message: type: string status: type: string examples: application/json: message: GitLab secret created status: 201 403: description: >- Request failed. User token not valid. examples: application/json: { "message": "Token is not valid." } 500: description: >- Request failed. Internal controller error. """ try: if current_user.is_authenticated: user = _get_user_from_invenio_user(current_user.email) else: user = get_user_from_token(request.args.get('access_token')) if 'code' in request.args: gitlab_code = request.args.get('code') parameters = "client_id={0}&" + \ "client_secret={1}&code={2}&" + \ "grant_type=authorization_code&redirect_uri={3}" parameters = parameters.format(REANA_GITLAB_OAUTH_APP_ID, REANA_GITLAB_OAUTH_APP_SECRET, gitlab_code, REANA_GITLAB_OAUTH_REDIRECT_URL) gitlab_response = requests.post(REANA_GITLAB_URL + '/oauth/token', data=parameters).content secrets_store = REANAUserSecretsStore(str(user.id_)) secrets_store.add_secrets(_format_gitlab_secrets(gitlab_response), overwrite=True) return jsonify({"message": "GitLab secret created"}), 201 else: return jsonify({"message": "OK"}), 200 except ValueError: return jsonify({"message": "Token is not valid."}), 403 except Exception as e: logging.error(traceback.format_exc()) return jsonify({"message": str(e)}), 500