Exemplo n.º 1
0
def GetImageFromFile(path):
  """Builds a GooglePrivacyDlpV2ByteContentItem message from a path.

  Will attempt to set message.type from file extension (if present).

  Args:
    path: the path arg given to the command.

  Raises:
    ImageFileError: if the image path does not exist and does not have a valid
    extension.

  Returns:
    GooglePrivacyDlpV2ByteContentItem: an message containing image data for
    the API on the image to analyze.
  """
  extension = os.path.splitext(path)[-1].lower()
  extension = extension or 'n_a'
  image_item = _GetMessageClass('GooglePrivacyDlpV2ByteContentItem')
  if os.path.isfile(path) and _ValidateExtension(extension):
    enum_val = arg_utils.ChoiceToEnum(VALID_IMAGE_EXTENSIONS[extension],
                                      image_item.TypeValueValuesEnum)
    image = image_item(data=files.ReadBinaryFileContents(path), type=enum_val)
  else:
    raise ImageFileError(
        'The image path [{}] does not exist or has an invalid extension. '
        'Must be one of [jpg, jpeg, png, bmp or svg]. '
        'Please double-check your input and try again.'.format(path))
  return image
Exemplo n.º 2
0
    def send(self, req, **kwargs):  # pylint: disable=unused-argument
        """Return the file specified by the given request.

    Args:
      req: PreparedRequest
      **kwargs: kwargs can include values for headers, timeout, stream, etc.

    Returns:
      requests.Response object
    """
        path = files.NormalizePathFromURL(req.path_url)
        response = requests.Response()

        response.status_code, response.reason = self._chkpath(req.method, path)
        if response.status_code == 200 and req.method.lower() != "head":
            try:
                response.raw = io.BytesIO(files.ReadBinaryFileContents(path))
            except (OSError, IOError) as err:
                response.status_code = 500
                response.reason = str(err)

        response.url = req.url
        response.request = req
        response.connection = self
        return response
Exemplo n.º 3
0
def GetImageFromPath(path):
    """Builds an Image message from a path.

  Args:
    path: the path arg given to the command.

  Raises:
    ImagePathError: if the image path does not exist and does not seem to be
        a remote URI.

  Returns:
    alpha_vision_v1_messages.Image: an image message containing information
      for the API on the image to analyze.
  """
    messages = product_util.GetApiMessages(
        product_util.PRODUCTS_SEARCH_VERSION)
    image = messages.Image()

    if os.path.isfile(path):
        image.content = files.ReadBinaryFileContents(path)
    elif storage_util.ObjectReference.IsStorageUrl(path):
        image.source = messages.ImageSource(imageUri=path)
    else:
        raise product_util.GcsPathError(obj='image', data=path)
    return image
Exemplo n.º 4
0
    def testRedactWithOutputFile(self, track, info_types, expected_info_types):
        properties.VALUES.core.user_output_enabled.Set(True)
        self.track = track
        output_file = os.path.join(self.temp_path, 'output.csv')
        test_content = 'test,content'
        redacted_content = b'redacted,content'
        redact_request = self.MakeTextRedactRequest(test_content,
                                                    expected_info_types,
                                                    'POSSIBLE', 'info-type')
        redact_response = self.MakeTextRedactResponse(redacted_content,
                                                      expected_info_types,
                                                      'POSSIBLE', 'info-type',
                                                      None)
        self.client.projects_content.Deidentify.Expect(
            request=redact_request, response=redact_response)

        self.Run(
            'dlp text redact --content "{content}" --info-types {info_types} '
            '--replace-with-info-type --output-file {output}'.format(
                content=test_content,
                info_types=info_types,
                output=output_file))
        self.AssertErrContains(
            'The redacted contents can be viewed in [{}]'.format(output_file))
        self.assertEqual(redacted_content,
                         files.ReadBinaryFileContents(output_file))
Exemplo n.º 5
0
    def testRedactWithOutputFile(self, track):
        properties.VALUES.core.user_output_enabled.Set(True)
        self.track = track
        test_file = self.MakeTestTextFile(file_name='tmp.jpeg',
                                          contents=self.TEST_IMG_CONTENT)
        output_file = os.path.join(self.temp_path, 'output.jpeg')

        redact_request = self.MakeImageRedactRequest(
            file_type='IMAGE_JPEG',
            info_types=['PHONE_NUMBER'],
            min_likelihood='POSSIBLE',
            include_quote=False)

        redacted_content = b'redacted content'
        redact_response = self.msg.GooglePrivacyDlpV2RedactImageResponse(
            extractedText='Foo', redactedImage=redacted_content)
        self.client.projects_image.Redact.Expect(request=redact_request,
                                                 response=redact_response)
        self.assertEqual(
            redact_response,
            self.Run(
                'dlp images redact {content_file} '
                '--info-types PHONE_NUMBER --output-file {output_file}'.format(
                    content_file=test_file, output_file=output_file)))
        self.AssertErrContains(
            'The redacted contents can be viewed in [{}]'.format(output_file))
        self.assertEqual(redacted_content,
                         files.ReadBinaryFileContents(output_file))
Exemplo n.º 6
0
  def Run(self, args):
    project_ref = resources.REGISTRY.Parse(
        properties.VALUES.core.project.Get(required=True),
        collection='cloudresourcemanager.projects',
    )
    normalized_artifact_url = binauthz_command_util.NormalizeArtifactUrl(
        args.artifact_url)
    signature = console_io.ReadFromFileOrStdin(args.signature_file, binary=True)
    if args.payload_file:
      payload = files.ReadBinaryFileContents(args.payload_file)
    else:
      payload = binauthz_command_util.MakeSignaturePayload(
          normalized_artifact_url)

    attestor_ref = args.CONCEPTS.attestor.Parse()
    api_version = apis.GetApiVersion(self.ReleaseTrack())
    attestor = attestors.Client(api_version).Get(attestor_ref)
    # TODO(b/79709480): Add other types of attestors if/when supported.
    note_ref = resources.REGISTRY.ParseResourceId(
        'containeranalysis.projects.notes',
        attestor.userOwnedDrydockNote.noteReference, {})

    return containeranalysis.Client().CreateGenericAttestationOccurrence(
        project_ref=project_ref,
        note_ref=note_ref,
        artifact_url=normalized_artifact_url,
        public_key_id=args.public_key_id,
        signature=signature,
        plaintext=payload,
    )
Exemplo n.º 7
0
 def _ReadFile(self, path, max_bytes):
     data = files.ReadBinaryFileContents(path)
     if len(data) > max_bytes:
         raise exceptions.BadFileException(
             'The file is larger than the maximum size of {0} bytes.'.
             format(max_bytes))
     return data
Exemplo n.º 8
0
def GetImageFromPath(path):
    """Builds an Image message from a path.

  Args:
    path: the path arg given to the command.

  Raises:
    ImagePathError: if the image path does not exist and does not seem to be
        a remote URI.

  Returns:
    vision_v1_messages.Image: an image message containing information for the
        API on the image to analyze.
  """
    messages = apis.GetMessagesModule(VISION_API, VISION_API_VERSION)
    image = messages.Image()

    if os.path.isfile(path):
        image.content = files.ReadBinaryFileContents(path)
    elif re.match(IMAGE_URI_FORMAT, path):
        image.source = messages.ImageSource(imageUri=path)
    else:
        raise ImagePathError(
            'The image path does not exist locally or is not properly formatted. '
            'A URI for a remote image must be a Google Cloud Storage image URI, '
            'which must be in the form `gs://bucket_name/object_name`, or a '
            'publicly accessible image HTTP/HTTPS URL. Please double-check your '
            'input and try again.')
    return image
Exemplo n.º 9
0
    def GetAudioFromPath(path):
        """Determine whether path to audio is local, build RecognitionAudio message.

    Args:
      path: str, the path to the audio.

    Raises:
      AudioException: If audio is not found locally and does not appear to be
        Google Cloud Storage URL.

    Returns:
      speech_v1_messages.RecognitionAudio, the audio message.
    """
        messages = apis.GetMessagesModule(SPEECH_API, version)
        audio = messages.RecognitionAudio()

        if os.path.isfile(path):
            audio.content = files.ReadBinaryFileContents(path)
        elif storage_util.ObjectReference.IsStorageUrl(path):
            audio.uri = path
        else:
            raise AudioException(
                'Invalid audio source [{}]. The source must either be a local path '
                'or a Google Cloud Storage URL (such as gs://bucket/object).'.
                format(path))

        return audio
Exemplo n.º 10
0
 def GetFileContents(compared_file):
     try:
         contents = file_utils.ReadFileContents(compared_file)
         is_binary = False
     except UnicodeError:
         contents = file_utils.ReadBinaryFileContents(compared_file)
         is_binary = True
     return (contents, is_binary)
Exemplo n.º 11
0
def ReadServiceConfigFile(file_path):
    try:
        if IsProtoDescriptor(file_path):
            return files.ReadBinaryFileContents(file_path)
        return files.ReadFileContents(file_path)
    except files.Error as ex:
        raise calliope_exceptions.BadFileException(
            'Could not open service config file [{0}]: {1}'.format(
                file_path, ex))
Exemplo n.º 12
0
def GetFileContentAndFileType(file_path):
  """Helper function used for read file and determine file type."""
  file_content = file_utils.ReadBinaryFileContents(file_path)
  file_type = ''
  if file_path.endswith('.bin'):
    file_type = 'BIN'
  else:
    file_type = 'X509'
  return file_content, file_type
Exemplo n.º 13
0
def CredentialsFromP12File(filename, account, password=None):
    """Create p12 service account credentials from given file."""

    try:
        private_key = files.ReadBinaryFileContents(filename)
    except EnvironmentError as e:
        raise BadCredentialFileException('Could not read file {0}'.format(e))

    return CredentialsFromP12Key(private_key, account, password)
Exemplo n.º 14
0
    def _HandleFileWriteImpl(self,
                             is_binary,
                             path,
                             private=False,
                             append=False,
                             create_path=False):
        """Intercept calls to write files."""
        abs_path = os.path.abspath(path)

        cwd = os.path.abspath(os.getcwd())
        config_dir = os.path.abspath(config.Paths().global_config_dir)
        home_dir = os.path.abspath(files.GetHomeDir())
        is_known_location = (abs_path.startswith(cwd)
                             or abs_path.startswith(home_dir)
                             or abs_path.startswith(config_dir))
        # We have to do this because under tests, all the above are actually under
        # the temp directory because they are mocked out.
        temp_dir = os.path.abspath(tempfile.gettempdir())
        is_temp = abs_path.startswith(temp_dir) and not is_known_location
        is_compute_ssh_hosts_file = path.endswith(
            os.path.join('.ssh', 'google_compute_known_hosts'))

        if not (is_known_location or is_temp or is_compute_ssh_hosts_file):
            raise Error(
                'Command is attempting to write file outside of current '
                'working directory: [{}]'.format(abs_path))

        # Pass through the write like normal
        if is_binary:
            with self._orig_binary_file_writer(path,
                                               private=private,
                                               create_path=create_path) as fw:
                yield fw
        else:
            with self._orig_file_writer(path,
                                        private=private,
                                        append=append,
                                        create_path=create_path) as fw:
                yield fw

        # After they close it, capture what happened.
        if abs_path.startswith(config_dir) or is_temp:
            # Ignore any files written to config or tmp for assertion purposes.
            return

        current_event = self._GetOrCreateNextEvent(
            events_lib.EventType.FILE_WRITTEN)
        if is_binary:
            contents = files.ReadBinaryFileContents(path)
        else:
            contents = files.ReadFileContents(path)

        if abs_path.startswith(home_dir):
            path = '~' + abs_path[len(home_dir):]

        self._Handle(current_event, path, contents, private)
Exemplo n.º 15
0
def UpdateRequestWithInput(unused_ref, args, request):
  """The Python hook for yaml commands to inject content into the request."""
  path = args.input_path
  if os.path.isfile(path):
    request.inputContent = files.ReadBinaryFileContents(path)
  elif storage_util.ObjectReference.IsStorageUrl(path):
    request.inputUri = path
  else:
    raise VideoUriFormatError(INPUT_ERROR_MESSAGE.format(path))
  return request
Exemplo n.º 16
0
    def Run(self, args):
        project_ref = resources.REGISTRY.Parse(
            properties.VALUES.core.project.Get(required=True),
            collection='cloudresourcemanager.projects',
        )
        normalized_artifact_url = binauthz_command_util.NormalizeArtifactUrl(
            args.artifact_url)
        signature = console_io.ReadFromFileOrStdin(args.signature_file,
                                                   binary=True)
        if args.payload_file:
            payload = files.ReadBinaryFileContents(args.payload_file)
        else:
            payload = binauthz_command_util.MakeSignaturePayload(
                normalized_artifact_url)

        attestor_ref = args.CONCEPTS.attestor.Parse()
        api_version = apis.GetApiVersion(self.ReleaseTrack())
        attestor = attestors.Client(api_version).Get(attestor_ref)
        # TODO(b/79709480): Add other types of attestors if/when supported.
        note_ref = resources.REGISTRY.ParseResourceId(
            'containeranalysis.projects.notes',
            attestor.userOwnedDrydockNote.noteReference, {})

        validation_enabled = 'validate' in args and args.validate
        validation_callback = functools.partial(
            validation.validate_attestation,
            attestor_ref=attestor_ref,
            api_version=api_version)

        ca_api_version = ca_apis.GetApiVersion(self.ReleaseTrack())
        # TODO(b/138859339): Remove when remainder of surface migrated to V1 API.
        if ca_api_version == ca_apis.V1:
            return containeranalysis.Client(
                ca_api_version).CreateAttestationOccurrence(
                    project_ref=project_ref,
                    note_ref=note_ref,
                    artifact_url=normalized_artifact_url,
                    public_key_id=args.public_key_id,
                    signature=signature,
                    plaintext=payload,
                    validation_callback=(validation_callback
                                         if validation_enabled else None),
                )
        else:
            return containeranalysis.Client(
                ca_api_version).CreateGenericAttestationOccurrence(
                    project_ref=project_ref,
                    note_ref=note_ref,
                    artifact_url=normalized_artifact_url,
                    public_key_id=args.public_key_id,
                    signature=signature,
                    plaintext=payload,
                )
def GetFileContentAndFileType(file_path):
    """Helper function used for read file and determine file type."""
    file_content = file_utils.ReadBinaryFileContents(file_path)
    file_type = ''
    if file_path.endswith('.bin'):
        file_type = 'BIN'
    else:
        if not IsDERForm(file_content):
            raise utils.IncorrectX509FormError(
                'File is not in X509 binary DER form.')
        file_type = 'X509'
    return file_content, file_type
Exemplo n.º 18
0
  def Run(self, args):
    client, messages = util.GetClientAndMessages()
    response = client.projects_serviceAccounts.SignBlob(
        messages.IamProjectsServiceAccountsSignBlobRequest(
            name=iam_util.EmailToAccountResourceName(args.iam_account),
            signBlobRequest=messages.SignBlobRequest(
                bytesToSign=files.ReadBinaryFileContents(args.input))))

    log.WriteToFileOrStdout(
        args.output, content=response.signature, binary=True)
    log.status.Print(
        'signed blob [{0}] as [{1}] for [{2}] using key [{3}]'.format(
            args.input, args.output, args.iam_account, response.keyId))
Exemplo n.º 19
0
def Base64EncodedFileContents(filename):
  """Reads the provided file, and returns its contents, base64-encoded.

  Args:
    filename: The path to the file, absolute or relative to the current working
      directory.

  Returns:
    A string, the contents of filename, base64-encoded.

  Raises:
   files.Error: if the file cannot be read.
  """
  return base64.b64encode(
      files.ReadBinaryFileContents(files.ExpandHomeDir(filename)))
Exemplo n.º 20
0
def GetRecognitionAudioFromPath(path, version):
  """Determine whether path to audio is local, set RecognitionAudio message."""
  messages = apis.GetMessagesModule(SPEECH_API, version)
  audio = messages.RecognitionAudio()

  if os.path.isfile(path):
    audio.content = files.ReadBinaryFileContents(path)
  elif storage_util.ObjectReference.IsStorageUrl(path):
    audio.uri = path
  else:
    raise AudioException(
        'Invalid audio source [{}]. The source must either be a local path '
        'or a Google Cloud Storage URL (such as gs://bucket/object).'.format(
            path))
  return audio
Exemplo n.º 21
0
def GetCommandFromFileProcessor(path):
  """Builds a binary data for a SendCommandToDeviceRequest message from a path.

  Args:
    path: the path arg given to the command.

  Raises:
    ValueError: if the path does not exist or can not be read.

  Returns:
    binary data to be set on a message.
  """
  try:
    return files.ReadBinaryFileContents(path)

  except Exception as e:
    raise ValueError('Command File [{}] can not be opened: {}'.format(path, e))
def GetFileContents(file):
  """Returns the file contents and whether or not the file contains binary data.

  Args:
    file: A file path.

  Returns:
    A tuple of the file contents and whether or not the file contains binary
    contents.
  """
  try:
    contents = file_utils.ReadFileContents(file)
    is_binary = False
  except UnicodeError:
    contents = file_utils.ReadBinaryFileContents(file)
    is_binary = True
  return contents, is_binary
Exemplo n.º 23
0
def ReadFromFileOrStdin(path, binary):
    """Returns the contents of the specified file or stdin if path is '-'.

  Args:
    path: str, The path of the file to read.
    binary: bool, True to open the file in binary mode.

  Raises:
    Error: If the file cannot be read or is larger than max_bytes.

  Returns:
    The contents of the file.
  """
    if path == '-':
        return ReadStdin(binary=binary)
    if binary:
        return files.ReadBinaryFileContents(path)
    return files.ReadFileContents(path)
Exemplo n.º 24
0
  def Run(self, args):
    """Signs the specified URL and optionally also validates it.

    Args:
      args: The arguments passed to this command.

    Returns:
      Returns a dictionary. The 'signedUrl' key in the dictionary maps to the
      Signed URL. The 'validationResponseCode' key in the dictionary maps to
      the response code obtained for the HEAD request issued to the Signed URL.
    """
    key_value = files.ReadBinaryFileContents(args.key_file).rstrip()
    result = {}
    result['signedUrl'] = sign_url_utils.SignUrl(args.url, args.key_name,
                                                 key_value, args.expires_in)

    if args.validate:
      result['validationResponseCode'] = sign_url_utils.ValidateSignedUrl(
          result['signedUrl'])

    return result
Exemplo n.º 25
0
def GetResourceFromFile(path):
    """Gets the given resource as a byte string.

  This is similar to GetResource(), but uses file paths instead of module names.

  Args:
    path: str, filesystem like path to a file/resource.

  Returns:
    The contents of the resource as a byte string.

  Raises:
    IOError: if resource is not found under given path.
  """
    if os.path.isfile(path):
        return files.ReadBinaryFileContents(path)

    importer = pkgutil.get_importer(os.path.dirname(path))
    if hasattr(importer, 'get_data'):
        return importer.get_data(path)

    raise IOError('File not found {0}'.format(path))
Exemplo n.º 26
0
def GetDerCertificate(certificate_file):
    """Read certificate_file and return the certificate in DER encoding.

  Args:
    certificate_file: A file handle to the certificate in PEM or DER format.

  Returns:
    The certificate in DER encoding.

  Raises:
    BadArgumentException: The provided certificate failed to parse as a PEM.
  """
    data = files.ReadBinaryFileContents(certificate_file)
    if b'-----BEGIN CERTIFICATE-----' in data:
        certb64 = data.replace(b'-----BEGIN CERTIFICATE-----', b'', 1)
        certb64 = certb64.replace(b'-----END CERTIFICATE-----', b'', 1)
        # If there's another certificate detected afterwards
        if b'-----BEGIN CERTIFICATE-----' in certb64:
            raise exceptions.BadArgumentException(
                'certificate_file',
                'Cannot place multiple certificates in the same file : {}'.
                format(certificate_file))
        try:
            certb64 = certb64.replace(b'\r', b'').replace(b'\n', b'')
            # Since validate=True isn't supported on Python2's base64.b64decode,
            # re-encode output and compare to original.
            decoded = base64.b64decode(six.ensure_binary(certb64))
            encoded = base64.b64encode(decoded)
            if encoded != certb64:
                raise ValueError('Non-base64 digit found.')
        except Exception as e:
            raise exceptions.BadArgumentException(
                'certificate_file',
                'Recognized {} as a PEM file but failed during parsing : {}'.
                format(certificate_file, e))
        return decoded
    else:
        return data
Exemplo n.º 27
0
def ReadConfigData(args):
    """Read configuration data from the parsed arguments.

  See command_lib.iot.flags for the flag definitions.

  Args:
    args: a parsed argparse Namespace object containing config_data and
      config_file.

  Returns:
    str, the binary configuration data

  Raises:
    ValueError: unless exactly one of --config-data, --config-file given
  """
    if args.IsSpecified('config_data') and args.IsSpecified('config_file'):
        raise ValueError('Both --config-data and --config-file given.')
    if args.IsSpecified('config_data'):
        return http_encoding.Encode(args.config_data)
    elif args.IsSpecified('config_file'):
        return files.ReadBinaryFileContents(args.config_file)
    else:
        raise ValueError('Neither --config-data nor --config-file given.')
def GetSSLCredentials(mtls_enabled):
    """Returns SSL credentials."""
    ca_certs_file = properties.VALUES.core.custom_ca_certs_file.Get()
    certificate_chain = None
    private_key = None

    ca_config = context_aware.Config()
    if mtls_enabled and ca_config:
        log.debug('Using client certificate...')
        certificate_chain, private_key = (ca_config.client_cert_bytes,
                                          ca_config.client_key_bytes)

    if ca_certs_file or certificate_chain or private_key:
        if ca_certs_file:
            ca_certs = files.ReadBinaryFileContents(ca_certs_file)
        else:
            ca_certs = None

        return grpc.ssl_channel_credentials(
            root_certificates=ca_certs,
            certificate_chain=certificate_chain,
            private_key=private_key)
    return None
  def Run(self, args):
    project = arg_utils.GetFromNamespace(args, '--project', use_defaults=True)
    # This incidentally verifies that the kubeconfig and context args are valid.
    if self.ReleaseTrack() is base.ReleaseTrack.BETA or self.ReleaseTrack(
    ) is base.ReleaseTrack.ALPHA:
      api_adapter = gke_api_adapter.NewAPIAdapter('v1beta1')
    else:
      api_adapter = gke_api_adapter.NewAPIAdapter('v1')
    with kube_util.KubernetesClient(
        api_adapter=api_adapter,
        gke_uri=getattr(args, 'gke_uri', None),
        gke_cluster=getattr(args, 'gke_cluster', None),
        kubeconfig=getattr(args, 'kubeconfig', None),
        internal_ip=getattr(args, 'internal_ip', False),
        cross_connect_subnetwork=getattr(args, 'cross_connect_subnetwork',
                                         None),
        private_endpoint_fqdn=getattr(args, 'private_endpoint_fqdn', None),
        context=getattr(args, 'context', None),
        public_issuer_url=getattr(args, 'public_issuer_url', None),
        enable_workload_identity=getattr(args, 'enable_workload_identity',
                                         False),
    ) as kube_client:
      location = getattr(args, 'location', 'global')
      if location is None:
        location = 'global'
      kube_client.CheckClusterAdminPermissions()
      kube_util.ValidateClusterIdentifierFlags(kube_client, args)
      if self.ReleaseTrack() is not base.ReleaseTrack.GA:
        flags.VerifyGetCredentialsFlags(args)
      uuid = kube_util.GetClusterUUID(kube_client)
      # Read the service account files provided in the arguments early, in order
      # to catch invalid files before performing mutating operations.
      # Service Account key file is required if Workload Identity is not
      # enabled.
      # If Workload Identity is enabled, then the Connect Agent uses
      # a Kubernetes Service Account token instead and hence a Google Cloud
      # Platform Service Account key is not required.
      service_account_key_data = ''
      if args.service_account_key_file:
        try:
          service_account_key_data = hub_util.Base64EncodedFileContents(
              args.service_account_key_file)
        except files.Error as e:
          raise exceptions.Error('Could not process {}: {}'.format(
              SERVICE_ACCOUNT_KEY_FILE_FLAG, e))

      docker_credential_data = None
      if args.docker_credential_file:
        try:
          file_content = files.ReadBinaryFileContents(
              files.ExpandHomeDir(args.docker_credential_file))
          docker_credential_data = six.ensure_str(
              file_content, encoding='utf-8')
        except files.Error as e:
          raise exceptions.Error('Could not process {}: {}'.format(
              DOCKER_CREDENTIAL_FILE_FLAG, e))

      gke_cluster_self_link = kube_client.processor.gke_cluster_self_link
      issuer_url = None
      private_keyset_json = None
      if args.enable_workload_identity:
        # public_issuer_url can be None or given by user or gke_cluster_uri
        # (incase of a gke cluster).
        # args.public_issuer_url takes precedence over gke_cluster_uri.
        public_issuer_url = args.public_issuer_url or kube_client.processor.gke_cluster_uri or None

        try:
          openid_config_json = six.ensure_str(
              kube_client.GetOpenIDConfiguration(issuer_url=public_issuer_url),
              encoding='utf-8')
        except Exception as e:  # pylint: disable=broad-except
          raise exceptions.Error(
              'Error getting the OpenID Provider Configuration: '
              '{}'.format(e))

        # Extract the issuer URL from the discovery doc.
        issuer_url = json.loads(openid_config_json).get('issuer')
        if not issuer_url:
          raise exceptions.Error(
              'Invalid OpenID Config: '
              'missing issuer: {}'.format(openid_config_json))
        # Ensure public_issuer_url (only non-empty) matches what came back in
        # the discovery doc.
        if public_issuer_url and (public_issuer_url != issuer_url):
          raise exceptions.Error('--public-issuer-url {} did not match issuer '
                                 'returned in discovery doc: {}'.format(
                                     public_issuer_url, issuer_url))

        # In the private issuer case, we set private_keyset_json,
        # which is used later to upload the JWKS
        # in the Fleet Membership.
        if args.has_private_issuer:
          private_keyset_json = kube_client.GetOpenIDKeyset()

      # Attempt to create a membership.
      already_exists = False

      obj = None
      # For backward compatiblity, check if a membership was previously created
      # using the cluster uuid.
      parent = api_util.ParentRef(project, location)
      membership_id = uuid
      resource_name = api_util.MembershipRef(project, location, uuid)
      obj = self._CheckMembershipWithUUID(resource_name, args.CLUSTER_NAME)

      # get api version version to pass into create/update membership
      api_server_version = kube_util.GetClusterServerVersion(kube_client)
      if obj:
        # The membership exists and has the same description.
        already_exists = True
      else:
        # Attempt to create a new membership using cluster_name.
        membership_id = args.CLUSTER_NAME
        resource_name = api_util.MembershipRef(project, location,
                                               args.CLUSTER_NAME)
        try:
          self._VerifyClusterExclusivity(kube_client, parent, membership_id)
          obj = api_util.CreateMembership(project, args.CLUSTER_NAME,
                                          args.CLUSTER_NAME, location,
                                          gke_cluster_self_link, uuid,
                                          self.ReleaseTrack(), issuer_url,
                                          private_keyset_json,
                                          api_server_version)
          # Generate CRD Manifest should only be called afer create/update.
          self._InstallOrUpdateExclusivityArtifacts(kube_client, resource_name)
        except apitools_exceptions.HttpConflictError as e:
          # If the error is not due to the object already existing, re-raise.
          error = core_api_exceptions.HttpErrorPayload(e)
          if error.status_description != 'ALREADY_EXISTS':
            raise
          obj = api_util.GetMembership(resource_name, self.ReleaseTrack())
          if not obj.externalId:
            raise exceptions.Error(
                'invalid membership {0} does not have '
                'external_id field set. We cannot determine '
                'if registration is requested against a '
                'valid existing Membership. Consult the '
                'documentation on container fleet memberships '
                'update for more information or run gcloud '
                'container fleet memberships delete {0} if you '
                'are sure that this is an invalid or '
                'otherwise stale Membership'.format(membership_id))
          if obj.externalId != uuid:
            raise exceptions.Error(
                'membership {0} already exists in the project'
                ' with another cluster. If this operation is'
                ' intended, please run `gcloud container '
                'fleet memberships delete {0}` and register '
                'again.'.format(membership_id))

          # The membership exists with same cluster_name.
          already_exists = True

      # In case of an existing membership, check with the user to upgrade the
      # Connect-Agent.
      if already_exists:
        # Update Membership when required. Scenarios that require updates:
        # 1. membership.authority is set, but there is now no issuer URL.
        #    This means the user is disabling Workload Identity.
        # 2. membership.authority is not set, but there is now an
        #    issuer URL. This means the user is enabling Workload Identity.
        # 3. membership.authority is set, but the issuer URL is different
        #    from that set in membership.authority.issuer. This is technically
        #    an error, but we defer to validation in the API.
        # 4. membership.authority.oidcJwks is set, but the private keyset
        #    we got from the cluster differs from the keyset in the membership.
        #    This means the user is updating the public keys, and we should
        #    update to the latest keyset in the membership.
        if (  # scenario 1, disabling WI
            (obj.authority and not issuer_url) or
            # scenario 2, enabling WI
            (issuer_url and not obj.authority) or
            (obj.authority and
             # scenario 3, issuer changed
             ((obj.authority.issuer != issuer_url) or
              # scenario 4, JWKS changed
              (private_keyset_json and obj.authority.oidcJwks and
               (obj.authority.oidcJwks.decode('utf-8') != private_keyset_json))
             ))):
          console_io.PromptContinue(
              message=hub_util.GenerateWIUpdateMsgString(
                  obj, issuer_url, resource_name, args.CLUSTER_NAME),
              cancel_on_no=True)
          try:
            api_util.UpdateMembership(
                resource_name,
                obj,
                'authority',
                self.ReleaseTrack(),
                issuer_url=issuer_url,
                oidc_jwks=private_keyset_json)
            # Generate CRD Manifest should only be called afer create/update.
            self._InstallOrUpdateExclusivityArtifacts(kube_client,
                                                      resource_name)
            log.status.Print(
                'Updated the membership [{}] for the cluster [{}]'.format(
                    resource_name, args.CLUSTER_NAME))
          except Exception as e:
            raise exceptions.Error(
                'Error in updating the membership [{}]:{}'.format(
                    resource_name, e))
        else:
          console_io.PromptContinue(
              message='A membership [{}] for the cluster [{}] already exists. '
              'Continuing will reinstall the Connect agent deployment to use a '
              'new image (if one is available).'.format(resource_name,
                                                        args.CLUSTER_NAME),
              cancel_on_no=True)
      else:
        log.status.Print(
            'Created a new membership [{}] for the cluster [{}]'.format(
                resource_name, args.CLUSTER_NAME))

      # Attempt to update the existing agent deployment, or install a new agent
      # if necessary.
      try:
        agent_util.DeployConnectAgent(kube_client, args,
                                      service_account_key_data,
                                      docker_credential_data, resource_name,
                                      self.ReleaseTrack())
      except Exception as e:
        log.status.Print('Error in installing the Connect Agent: {}'.format(e))
        # In case of a new membership, we need to clean up membership and
        # resources if we failed to install the Connect Agent.
        if not already_exists:
          api_util.DeleteMembership(resource_name, self.ReleaseTrack())
          exclusivity_util.DeleteMembershipResources(kube_client)
        raise
      log.status.Print(
          'Finished registering the cluster [{}] with the Fleet.'.format(
              args.CLUSTER_NAME))
      return obj
Exemplo n.º 30
0
def _GetAgentRequestBody(source):
  if source.startswith('gs://'):
    return {'agentUri': source}
  else:
    return {'agentContent': files.ReadBinaryFileContents(source)}