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
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
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
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))
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))
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, )
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
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
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
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)
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))
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
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)
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)
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
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
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))
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)))
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
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
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)
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
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))
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
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
def _GetAgentRequestBody(source): if source.startswith('gs://'): return {'agentUri': source} else: return {'agentContent': files.ReadBinaryFileContents(source)}