■23/5/29 7:30PM
GCP hands-off 2
■プロジェクト削除時のサービスアカウントプロジェクトは30日保留される。その間サービスアカウント権限は生きており他プロジェクトでは動作する。しかし保留期間はプロジェクトを使用できずサービスアカウントを削除できず、個別に一つ一つ権限をはく奪するしかない。
サービスアカウントはプロジェクト削除前に、必要であれば事前に削除や無効化しておくことも検討する。
■連携
GoogleWorkspace -> GAS -> GCP Oauth + API -> GCP(Bigquery etc.)Python -> Gcloud sdk -> gcloud auth -> GCP(Bigquery etc.) <-> federation query/Connected sheet
Python(Oauth key) -> GCP認証情報(Oauth Key) + API -> GoogleWorkspace
GCPのクレデンシャルページでOauth2.0 client IDと鍵が発行でき、鍵でイケる
Pythonコードで鍵を指定すると実行時にログインを求められ、client IDとユーザIDを紐づけして実行することになる Authentication — gspread 5.7.2 documentation
Python でシンプルに OAuth 2 する (urllib + oauthlib) - Qiita
GCPのクレデンシャルページでAPIキーも発行でき、これは可能性はあるPython -> local csv/tsvが基本
●Python(SA key) -> GCP認証情報(SA Key) + API -> GoogleWorkspace
サービスアカウントでGWSにアクセスできないのでダメ
信頼しているドメインとのみ外部共有を許可する - Google Workspace 管理者 ヘルプ
サービス アカウント(ドメイン名の末尾が「gserviceaccount.com」)を信頼しているドメインにすることはできません
OUで許可するとイケるはずだが、、
●Python でGoogle docをイジるGoogle Docs APIを使って文章を作成してみる - より良いエンジニアを目指して (hatenablog.com)Google Docs APIを使って、索引を作成する #Python - Qiitaスコープ情報 Google API の OAuth 2.0 スコープ | Authorization | Google for Developers下記のURLの内容を検証すればよいPython のクイックスタート | Google Docs | Google for DevelopersGoogle CloudコンソールでOauth同意画面を設定Google Docs APIを有効化OAuth クライアントIDを作成シークレットJson ファイルができるのでDL(リネーム)コードにクレデンシャルJSONファイルとDocのURLに含まれるdocumentIDを記述→Python実行するとDocのデータが取れる(ローカルの場合は楽)
/// runのデプロイ時に設定を入れる方法について1)環境変数を(コンソール/cmd/コンテナymiのどれかで)設定:env=os environ.get("ENV") で使う。ログに出やすく非推奨2)シークレットマネージャ保存分を設定環境変数+コードでやるのと同じ?3)ボリュームを使う:クレデンを入れ、トークンの一時保存ができる?Cloud RunでSecret Managerを使いたい #Python - Qiita
※サービスアカウントでGWSを扱うにはGWSのOUで受け入れる設定が必要な場合がある
■secret managerに保存してコードで呼び出して使う Secret Managerのシークレットアクセサー権限 シークレット バージョンにアクセス | Secret Manager Documentation | Google Cloud (checksumをかけている)
from google.cloud import secretmanagerimport google.cloud.loggingimport loggingdef get_url(secret_key, project_num) logging.warning('####### secret_key' + str(secret_key) + '######') client = secretmanager.SecretManagerServiceClient() resource_name = "projects/()/secrets/()/versions/latest.format(project_num, secret_key) res = client.access_secret_version(resource_name) slack_url = res.payload.data.decode("utf-8") return slack_url
■API等でデータを取った時中身が分からない場合pramsが何かわからん時print(params)print(type(params))#<class 'proto.marshal.collections.maps.MapComposite'>#よくわからんクラスでもdirで保持するAttributeが分かるattributes = dir(params)print(attributes)#そこに含まれるメソッドも確認できるのでhelpするhelp(params.get) #prams.get('query')すると含まれるSQLが分かりこれで進める等
■Protocol buffersAPIの返りはGoogleは自社で開発したProtocol buffersを使っていようだたとえば下記が返るname: "projects/98765"parent: "folders/12345"project_id: "aaaaaa-bbbb-market"state: "ACTIVE"display_name: "aaaaaa-bbbb-market"create_time{ seconds: 1601250933 nanos: 820000000}update_time{ seconds: 1632826231 nanos: 634000000}etag: "W/a06910d9093db111"labels{ key: "budget_group" value: "cccc"}
これはprint (type(response))すると下記であり<class "google.cloud. resourcemanager v3.types.projects.Project"> print (response.project_id) で簡単にデコードし値取得できることが分かる
APIからの値を取るときのコードfrom google.cloud import resourcemanager_v3client = resourcemanager_v3.ProjectsClient()request resourcemanager v3.ListProjectsRequest{ #組織の場合、現状は権限がGOP側で用意がなく無理だった #parent organizations/12345678. parent="folders/1122233344"}page_result = client.list_projects(request=request)for response in page result: print(type(response)) print (response.project_id)
エンコードする場合 https://blog.imind.jp/entry/2019/12/28/124728pip install googleapis-common-protos でインスコ?sudo apt install protobuf-compiler でインスコ
sudo apt-get install protobuf-compiler でインスコ ※google提供のフォルダごと使用しようとして失敗した方法 ※googleapis/google/cloud/resourcemanager/v3/projects.proto at master · googleapis/googleapis · GitHub ※にprotoファイルがあるが丸々必要なので下記でDL ※git clone https://github.com/googleapis/googleapis.git ※バスを合わせてprojects.protoを使うが失敗 ※たとえば protoc python_out=. --proto_path=googleapis ./googleapis/google/cloud/resourcemanager/v3/projects.protoprojects.proto を下記の内容で一から作成することが必要だったsyntax proto3;
message Resource{ string name = 1; string parent = 2; string project_id = 3; string state = 4; string display_name = 5; map<string, string> create_time = 6; map<string, string> update_time = 7; string etag = 8; map<string, string> labels = 9;}そして下記を実行しコンパイルprotoc --python_out=. ./projects.protoprojects_pb2.pyが生成されるため、パッケージとして読みこみprotocol buffersを実行できるようになるimport projects_pb2.py※なおエラーで pip install U protobuf=3.20.0でダウングレードした
注意点としては、pythonとprotocol bufferとBigqueryの型合わせが必要 DateやTimestampはUNIXエポックからの日数や秒数に変換する必要がある Noneをstr 'None'や、int -1や、bool FalseにPythonで調整をするBigQuery Storage Write API を使用してデータを一括読み込み、ストリーミングする | Google Cloud
//UNIXエポックからの日数current_date = datetime.now()epoch = datetime(1970, 1, 1)record_date = (current_date - epoch).days
//UNIXエポックからの秒数data_string = str(date_v)dt_obj = datetime.fromisoformat(date_string.replace("Z","+00:00"))epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)seconds_since_epoch = (dt_obj - epoch).tatal_seconds()microseconds_since_epoch = int(seconds_since_epoch * 1e6)date_v = microseconds_since_epoch
■BQ APIクォータ割り当て超過(1000件insertしようとした)割り当てと上限 | BigQuery | Google Cloudテーブル変更1日1500件までテーブルメタデータ変更は10sあたり5回までテーブル当たりDMLの実行待ちキューは20件までテーブル当たり10sあたり25のDMLまで→各insertでスリープを5秒入れた import time time.sleep(5)
↓
上限がテーブル単位のためテーブル名を分けると回避できるらしいGCP BigQuery 応用編 ~制限について~ - 自称フルスタックエンジニアのぶろぐ。 (hatenablog.com)
↓■BQ streaming insert->BQ storage read/write APIの上限はDMLと別で、閾値が大きい
streaming insert -> Bigquery storage write API を使うINFORMATION_SCHEMAを用いたBigQueryのストレージ無駄遣い調査 - ZOZO TECH BLOGBigQuery Storage Write API を使用してデータを一括読み込み、ストリーミングする | Google Cloud
Storage Write API を使用したデータ読み込みのバッチ処理 | BigQuery | Google Cloud
CreateWriteStream > AppendRows(ループ) > FinalizeWriteStream > BatchCommitWriteStreams
をstart/append/send/close(write commit)の関数化し返り値でつなげた形にしたが sendをした後 proto_rows = types.ProtoRows() を掛け初期化する必要があった(offsetが倍々で増えたから)offsetで送信毎の開始行の設定も必要(一連の処理で件数を記憶しており0固定で処理を書けないようだった)
■Python/Client libraryの値をBQに入れるにあたり仕様書で型を調べる。STRUCTやクラスは紐解いて通常のカラムでBQに挿入timestampやboolやint64はそのままの形でBQに挿入BQ SQL:日付は値なしならNULLを入れる、数値やBool値はクォートで囲まないPythonでSQLインサート文を作るとき改行コードが含まれるものをセットするとSyntax errror:Unclosed string literalq = q.replace('//', '////') バックスラッシュをエスケープ、あるとイリーガルエスケープシーケンスとなる、raw文字列にしたい?
q = q.replace('/n', '//n') 改行をエスケープq = q.replace("'", "\\'") SQLが途切れないようシングルクォートをエスケープq = q.replace('/n', ' ') 改行を空白で置き換える
■変更の判断
変更で問題がでないか→PCにマウスと付けて問題が起こらないかという問題と相似、最終的に経験で判断するしか
■監査ログからSetIamのメソッドを取りBQ権限付与を検知するクエリ
WITH source AS(SELECT*FROM `project-logging.organization_audit_log_v2.cloudaudit_googleapis_com_activity_20*`WHERE_TABLE_SUFFIX = format_date('%y%m%d', current_date("Asia/Tokyo"))),project source AS(SELECTROW_NUMBER() OVER (ORDER BY timestamp) as id,*FROM sourceWHEREprotopayload_auditlog.methodName = 'SetlamPolicy'project_authorizationinfo AS(SELECTDISTINCTid,__ori.resource.type as type,__ori.resource.labels.project_id as project_id,__ori.resource.labels.dataset_id as dataset_id,protopayload_auditlog.methodName as method_nameprotopayload_auditlog.resourceName as resource_name,protopayload_auditlog.authenticationInfo.principal Email as email_manipulator,authorizationInfo.resource as request_resource,authorizationInfo.permission as request_permission,authorizationInfo.granted as request_granted,protopayload_auditlog.requestMetadata.callerlp as callerlp,protopayload_auditlog.requestMetadata.callerSuppliedUserAgent as callerSuppliedUserAgent,FROM project_source AS __ori). UNNEST (protopayload_auditlog.authorizationInfo) AS authorizationInfoproject_bindingdeltas AS(SELECTid,--array_binding Deltas_project as binding Deltas_project,array_binding Deltas_project.action as action_project,array_binding Deltas_project.member as member_project,array_binding Deltas_project.role as role_project,timestampFROM project_source AS_ori,UNNEST (protopayload_auditlog.servicedata_v1_iam.policyDelta.bindingDeltas) AS array_binding Deltas_project),project_setiam AS(SELECT--*, except(id)type,project_id,dataset_id,method_name,resource_name,email_manipulator,request_resource,request_permission,request_granted,callerip,callerSuppliedUserAgent.action_project,member_project,role project.CAST(NULL AS STRING) AS metadataJson,CAST(NULL AS STRING) AS bindingDeltas_dataset,CASTINULLAS STRING AS action_dataset,CAST(NULL AS STRING) AS member_dataset,CAST(NULL AS STRING) AS role_dataset,CAST(NULL AS STRING) AS bindingDeltas_table,CAST(NULL AS STRING) AS action_table,CAST(NULL AS STRING) AS member_table,CAST(NULL AS STRING) AS role_table,timestampFROM project_authorizationinfoLEFT JOIN project_bindingdeltas ON project_authorizationinfo.id = project_bindingdeltas.idWHERE role_project LIKE 'roles/bigquery%),resource_source AS (SELECT__ori.resource.type as type,__ori.resource.labels.project_id as project id,__ori.resource.labels.dataset_id as dataset_id,protopayload_auditlog.methodName as method_name,protopayload_auditlog.resourceName as resource_name,protopayload_auditlog.authenticationInfo.principalEmail as email_manipulator,authorizationInfo.resource as request_resource,authorizationInfo.permission as request_permission,authorizationInfo.granted as request_granted,protopayload_auditlog.requestMetadata.callerlp as callerlp,protopayload_auditlog.requestMetadata.callerSuppliedUserAgent as callerSuppliedUserAgent,protopayload_auditiog.metadataJson,timestampFROM source AS __ori,UNNEST(protopayload_auditlog.authorizationInfo) AS authorizationInfo WHEREprotopayload_auditlog.methodName = 'google.iam.v1.IAMPolicy.SetlamPolicy' --AND timestamp= "2024-03-11 04:11:30.885258 UTC"),resource_id AS (SELECTROW_NUMBER() OVER (ORDER BY timestamp) as id,*FROM resource_source),resource_bq_dataset AS (SELECTid as id_dataset,json_extract(metadataJson, '$.datasetChange bindingDeltas') as bindingDeltas_dataset,json_extract(array_bindingDeltas_dataset, '$action') as action_dataset,json_extract(array_bindingDeltas_dataset, $.member') as member_dataset,json_extract(array_bindingDeltas_dataset, '$.role') as role_dataset,FROM resource_id,UNNEST(json query_array(metadataJson, '$.datasetChange.bindingDeltas')) AS array_bindingDeltas_dataset),resource_bq_table AS (SELECTid as id table,json_extract(metadataJson, '$.tableChange.bindingDeltas') as bindingDeltas_table,json extract(array_bindingDeltas_table, '$.action') as action table,json_extract(array_bindingDeltas_table. '$.member') as member table,json_extract(array_bindingDeltas_table, '$.role') as role_table,FROM resource_id,UNNEST(json query_array(metadataJson, '$.tableChange.bindingDeltas')) AS array_bindingDeltas_table),resource_setiam AS ( SELECT--*except(id, id_dataset, id_table)type,project_id,dataset_id,method_name,resource_name,email_manipulator,request_resource,request_permission,request_granted,callerlp,callerSuppliedUserAgent,CAST(NULL AS STRING) AS action_project,CAST(NULL AS STRING) AS member_project,CAST(NULL AS STRING) AS role_project,metadataJson,bindingDeltas_dataset,action_dataset,member_dataset,role_dataset,bindingDeltas_table,action_table,member_table,role_table,timestampFROM resource_idLEFT JOIN resource_bq_dataset ON resource_id.id = resource_bq_dataset.id_datasetLEFT JOIN resource_bq_table ON resource_id.id = resource_bq_table.id_table)SELECT * FROM project_setiamUNION ALLSELECT * FROM resource_setiam
■BQからCloudSQLにデータを入れる (GCSを経由する、コマンドやPythonがあるbq query --use_legacy_sql=false 'CREATE OR REPLACE TABLE `prj.ds._table` AS SELECT FROM `prj.ds.view`';bq extract -destination_format CSV 'prj.ds._table' gs://bucket/tbl.csvgcloud sql import csv インスタンス名 gs://bucket/tbl.csv --database=データベース名 --table=テーブル名
■ログの重複をなくす
import google.cloud.loggingimport logging
# クライアントの作成client = google.cloud.logging.Client()
# Cloud Logging ハンドラを追加client.get_default_handler()client.setup_logging()
# 既存のハンドラをすべて削除for handler in logging.root.handlers[:]: logging.root.removeHandler(handler)
# 新しいハンドラを追加logging.basicConfig(level=logging.INFO)
# logging.basicConfig(level=logging.DEBUG) # DEBUG レベルからすべてのレベルを記録
# propagate を無効にして重複を防ぐlogger = logging.getLogger()logger.propagate = False
# 各ログレベルでテストlogging.debug('This is a DEBUG log')logging.info('This is an INFO log')logging.warning('This is a WARNING log')logging.error('This is an ERROR log')logging.critical('This is a CRITICAL log')
■何度かAPIコールを繰り返す
def safe_replace_text(document_id, old_text, new_text, max_attempts=3): for attempt in range(max_attempts): try: replace_text(document_id, old_text, new_text) break # 成功した場合はループを抜ける except Exception as e: print(f"Attempt {attempt + 1} failed: {e}") if attempt == max_attempts - 1: print("Reached maximum attempts.")
■Exponential Backoffで時間を指数級数的にゆらぎながら増やすリトライimport timeimport randomdef exponential_backoff(max_retries=5, base_wait_time=1, max_wait_time=32): retries = 0 while retries < max_retries: try: # APIリクエストの送信 response = send_request() if response.status_code == 200: return response # 成功時に結果を返す except Exception as e: wait_time = min(base_wait_time * (2 ** retries), max_wait_time) wait_time += random.uniform(0, 1) # ランダムなズレを追加(Jitter) print(f"Retrying in {wait_time} seconds...") time.sleep(wait_time) retries += 1 raise Exception("Max retries reached, request failed")
クォータの増加の依頼もできるが、基本的に下記の上限がある
1. Google Docs API の利用上限- ユーザーごとの1分あたりのリクエスト数:
- プロジェクトごとの1日あたりのリクエスト数:
- プロジェクトごとに1日100万リクエスト(デフォルト)
これらの制限を超えると、リクエストが拒否されるか、APIを利用できなくなることがあります。
2. Google Drive API の利用上限- ユーザーごとの100秒あたりのリクエスト数:
- プロジェクトごとの1日あたりのリクエスト数:
- ユーザーごとのデータ転送量の制限:
- 読み込みは750GB/日/ユーザー
- 書き込みはユーザーごとの制限が異なるため、大量のデータ処理を行う場合は注意が必要
Comment (0)
■23/4/23 9:24PM
false charge
false charge → 事実無根の告発(特に法的な場面で)calumniation / calumny → 悪意ある嘘を流すこと(一般的な誹謗中傷)defamation → 名誉毀損(法的な影響があることが多い)frame-up → 罠にはめるために虚偽の証拠を作る(策略的)
■冤罪
冤罪だと否認をすると勾留がつづき、結局無職になる、否認ではなく弁護士呼び微物検索を要求
駅員に拘束され警察に引き渡しで現行犯が成立、事務所には行かず駅で弁護士を呼ぶ、駅で警察対応 (現行犯なら逮捕状なしに警察官でなく一般人でも逮捕ができる)
起訴されると99%有罪だったか?日本の捜査はほぼ自白が証拠だったか?
>冤罪なら自白はゆすりがあっても絶対駄目
//// 対応策
弁護士を呼ぶ
駅事務所には行かず現場で対応
警察に「何も触っていないのでDNA検査を」求める、きちんと捜査してもらう
名刺を渡してでも拘束を避ける(連絡が取れる民間人からの逃走でなくなる??)は良くなさそう
//// とりあえず下記を覚える↓↓↓↓↓
「この人痴漢です!」そう叫ばれたときに絶対にしてはいけない"あること" 「常識的な行為」が冤罪につながる | PRESIDENT Online(プレジデントオンライン)
https://togetter.com/li/1360859
可能ならばスマホで最寄りの弁護士会をチェックし、「当番弁護士の対応を依頼します」と伝え
「痴漢冤罪に巻き込まれていること」「どこの駅で警察を呼ばれた」このふたつを必ず家族に伝え
すぐに微物検索を要求、取り調べもネタが上がるまで一切話さない→結果何も証拠が出ずおしまいになる
警察はやった前提でなかば脅しの取り調べをしてきますが、心折れて「やった」と言ってしまえば即アウト、痴漢は本人の自供がかなり大きい証拠になります。認めるまで出さないと言われても、留置は48時間、送検後の勾留も最大20日これを耐えれば不起訴になる可能性が高くなります
取り調べがあまりにも脅迫まがいで耐えられそうになければ、録画を要求しましょう。取り調べの録画は容疑者の権利なので警察は拒否できません。部屋に入る前に録画操作をするので、それもちゃんと確認する
調書には署名しない
逮捕された時に弁護士のあてがなければ、「当番弁護士を呼んでください、それまで何も話しません」の一点張り
本当にやっていなければ否認を貫けば大丈夫ですが、弁護士を立てる場合お金がなくても国選弁護人がつけられます、原則国がお金だしてくれます
携帯を押収して中を調べようとしますがパスコードを教える必要はありません。調べたけりゃ令状取って自分で解析しなはれや。
また、あたかも強制かのようにや話してくるDNA採取は任意
持病がある健康面の理由は考慮される
身柄拘束中は所持品全て没収されます。それどころか留置施設から取調室にいくちょっとの移動でもいちいちワッパはめますから。外部へは連絡取れないので、弁護士に連絡を依頼するしかありません。警察も連絡はしてくれません
===============
■職質
不審者に対するもので任意で行われる、だが実質は簡単には断れない
変に逃げると公務執行妨害に捻じ曲げられる可能性もある
もしあまりに不当と思われるなら
「職質の要件は、犯罪を見た/聴いた/した直後に見える等だがどれに該当か?」
「任意であり、中には顧客の個人情報があり応じられない、どれが個人情報かを示すだけでも機密保持違反、断る」
「押し問答もかれこれx時間を経過しており実質的な不当逮捕である」
110番し「○○警察署の○○を名乗る警官らに不当な拘束を○○場所で受けている。助けて欲しい」
https://twitter.com/yokotindeka_DJ/status/1238985677808648192
===============
https://anond.hatelabo.jp/20191028031522
逮捕の記憶
弁護士の電話番号、身元引受人の電話番号を覚えておく→覚え易い、あるいは暗号で出てくるようにする
https://kobe.vbest.jp/
0120-666-694(フリーダイヤル、オーメン、69し)
Comment (0)
■23/4/23 9:12PM
Bay Bay Bay
ebayはSellerからオファーがあり値引きしてくる。破壊力あるな。ただ購入が面倒だった。
ebayでの問題1)日本には送ってくれない場合がある2)日本に送ってくれるが住所が日本語だと売主でキャンセルされる決済での問題3)クレカ会社で支払いを止められている場合がある4)Paypalで各種証明書が必要で止められている場合がある(クレカ認証も要るはず5)google payでの決済ができない(クレカ側で止められているのでは?↓
対処
↓1)米国転送住所 shipito.com が使える オレゴン倉庫は消費税が掛からないが有料で月10ドル calの10%弱の消費税が掛からず送料も安くなるので一時契約する ebayに米国住所を登録するには米国電話番号が必要 skypeで毎月300円で発行ができるので一時契約する(MSのoutlookメールID) shipito.comに送付されたら日本に転送依頼をする2)ebayの送付先住所(米国)は英語にする(日本に送付可ならコレなくてもいい) 念のため日本の個人情報住所も英語にする(日本に送付可でもココは英語がいいかも) 念のためebayの言語設定を英語、場所を米国にする(上か下ナビにあるはず) その後に購入・決済手続きする方がいい3)クレカサイトのFAQで支払いできない時等で検索して対処4)Paypalは各種証明書を登録する。クレカ認証は確か少額課金で検証されるはず5)知らん
shipitoで送料見積もると安かったが、実際に荷物が届くと梱包が大きくかなり高い
米国内転送でshipitoでまとめて荷物一つで送ろうと思ったが、直接日本に送ってくれる相手なら直接の方が安いかもしれず良く考えよ解約すること shipito $10 / skype us phone num 300yen
解約していたはずが、SKYPE.COM/GO/BILL利用国LUで300円請求されていた
ログインIDを確認しログインし Manage features| Skype My Account で解約した
SkypeとかGoogleとか詐欺ってるよな
=========
流せるトイレブラシの使い方に「天才かよ」 真似したくなるトイレの掃除術 – grape [グレイプ] (grapee.jp)
昭和100年は、2025年/平成37年/令和7年だ。(昭和64年=平成元年/1989、平成31年=令和元年/2019)
西暦の下2桁から018(レイワ)を引くと令和、23-18=5なので令和5年
Comment (0)
Navi: < 7 | 8 | 9 | 10 >
-Home
-Column [133]
-Europe [9]
-Gadget [77]
-Web [137]
-Bike [4]
@/// BANGBOO BLOG ///