#author("2021-01-05T01:42:00+00:00","","")
#author("2021-01-05T06:14:39+00:00","","")
#mynavi(Azureメモ);

#html(){{
<style>
.images img {
    border: 1px solid #333;
}
.images .img_margin {
    margin: 0;
    display: inline-block;
}
</style>
}}

* 概要 [#if3d0093]
#html(<div class="pl10">)
#TODO
#html(</div>)

* 目次 [#v91ebec6]
#contents
- 関連
-- [[Azureメモ]]
- 参考
-- [[Azure AD ログインを使用するように App Service または Azure Functions アプリを構成する>https://docs.microsoft.com/ja-jp/azure/app-service/configure-authentication-provider-aad]]
-- [[サービス プリンシパルを使用して Azure Active Directory トークンを取得する>https://docs.microsoft.com/ja-jp/azure/databricks/dev-tools/api/latest/aad/service-prin-aad-token]]
-- [[Azure Active Directory 認証ライブラリを使用して Azure Active Directory トークンを取得する>https://docs.microsoft.com/ja-jp/azure/databricks/dev-tools/api/latest/aad/app-aad-token]]
-- [[Azure Active Directory トークンを使用して認証する>https://docs.microsoft.com/ja-jp/azure/databricks/dev-tools/api/latest/aad/]]
-- [[サービス間の呼び出し用にデーモン クライアント アプリケーションを構成する>https://docs.microsoft.com/ja-jp/azure/app-service/configure-authentication-provider-aad#configure-a-daemon-client-application-for-service-to-service-calls]]
-- https://github.com/Azure/azure-sdk-for-go
-- https://github.com/Azure-Samples/azure-sdk-for-go-samples
-- https://github.com/Azure/go-autorest/blob/master/autorest/azure/example/main.go
-- https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#UsernamePasswordConfig
-- https://godoc.org/github.com/Azure/go-autorest/autorest/adal#NewServicePrincipalTokenFromUsernamePassword
-- [[Microsoft ID プラットフォームと OAuth 2.0 認証コード フロー>https://docs.microsoft.com/ja-jp/azure/active-directory/develop/v2-oauth2-auth-code-flow]]

* 準備 [#u8b11c93]
#html(<div class="pl10">)

** リソース作成 [#p9c8653e]
#html(<div class="pl10">)

#html(){{
<div id="tabs1">
  <ul>
    <li><a href="#tabs1-0">0_env.sh</a></li>
    <li><a href="#tabs1-1">1_resources.sh</a></li>
    <li><a href="#tabs1-2">appservice/app.py</a></li>
    <li><a href="#tabs1-3">appservice/requirements.txt</a></li>
  </ul>
}}

// START tabs1-0
#html(<div id="tabs1-0">)

#mycode2(){{
#!/bin/bash

# 全てのリソース名に付与する接頭文字 (Storageアカウント名などは世界でユニークな必要があるので他ユーザと被らないような名前を付ける)
PREFIX=XXXXXXXXXXX

# リージョン
region=japaneast

# リソースグループ名
resourceGroup=${PREFIX}ResourceGroup

# App Service
webappName=${PREFIX}SampleApp
webappPlan=F1
}}

#html(</div>)
// END tabs1-0

// START tabs1-1
#html(<div id="tabs1-1">)

1_resources.sh
#mycode2(){{
#!/bin/bash

source ./0_env.sh

# リソースの作成
if [ "$1" == "--create" ]; then

    # リソースグループの作成
    echo az group create
    az group create --name $resourceGroup --location $region

    # App Service のデプロイ
    cd appservice
    az webapp up --sku $webappPlan -n $webappName -l $region -g ${resourceGroup}
    cd ../
fi

# リソースの削除
if [ "$1" == "--delete" ]; then
    az group delete --name $resourceGroup -y
fi
}}

#html(</div>)
// END tabs1-1

// START tabs1-2
#html(<div id="tabs1-2">)

appservice/app.py
#mycode2(){{
from flask import Flask
import json
import datetime

app = Flask(__name__)

@app.route("/hello", methods=['GET', 'POST'])
def hello():
    message = f"This is Sample response! ({datetime.datetime.now()})"
    return json.dumps({'message': message}), 200, {'Content-Type': 'application/json; charset=utf-8'}
}}

#html(</div>)
// END tabs1-2

// START tabs1-3
#html(<div id="tabs1-3">)

appservice/requirements.txt
#mycode2(){{
Flask
}}

#html(</div>)
// END tabs1-3


#html(</div>)
// END tabs1

#html(<script>$(function() { $("#tabs1").tabs(); });</script>)

#html(</div>)

** アクセス確認用のユーザ作成 [#v8731813]
#html(<div class="pl10">)

Azure Active Directory → ユーザ からアクアセス確認用のユーザを作成しておく。
#html(<div class="images">)
#ref(create_user.png,nolink);
#html(</div>)

#html(</div>)

** デプロイしたアプリのAAD認証を有効にする [#ea305a3d]
#html(<div class="pl10">)

App Service から対象のアプリを選択後、[認証/承認] を選択して以下の通り設定。
#html(<div class="images">)
#ref(app_auth_setting1.png,nolink);
#ref(app_auth_setting2.png,nolink);
#html(</div>)

#html(</div>)

** ブラウザからアプリにアクセスしてみる [#i4a63210]
#html(<div class="pl10">)
#TODO
#html(</div>)

#html(</div>)

* GoでAAD認証するコードの作成 [#h857abb1]
* プログラムからAAD認証する為の設定 [#a389290b]
#html(<div class="pl10">)
#TODO
#html(</div>)

* GoでAAD認証するコードの作成 [#h857abb1]
#html(<div class="pl10">)

test.go
#mycode2(){{
package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "time"

    "github.com/Azure/go-autorest/autorest/azure/auth"
    "github.com/Azure/go-autorest/autorest/adal"
    //"github.com/Azure/go-autorest/autorest/azure"
)

const clientID string = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
const tenantID string = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
const username string = "xxxxxxxx@xxxxxxxx.onmicrosoft.com"
const password string = "xxxxxxxxxx"
//const resource string = "https://graph.microsoft.com/"
//const resource string = "https://graph.windows.net/"
//const resource string = "https://xxxxxxxxxx.azurewebsites.net"
const resource string = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
const apiUrl   string = "https://xxxxxxxxxx.azurewebsites.net/hello"

func getToken() string {

    // トークンの取得
    config := auth.NewUsernamePasswordConfig(username, password, clientID, tenantID)
    fmt.Printf("ClientID:  : %v\n"   , config.ClientID)
    fmt.Printf("Username   : %v\n"   , config.Username)
    fmt.Printf("Password   : %v\n"   , config.Username)
    fmt.Printf("TenantID   : %v\n"   , config.TenantID)
    fmt.Printf("AADEndpoint: %v\n"   , config.AADEndpoint)
    fmt.Printf("Resource   : %v\n"   , config.Resource)

    config.Resource = resource

    //oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, tenantID)
    oauthConfig, err := adal.NewOAuthConfig(config.AADEndpoint, tenantID)
    if err != nil {
        fmt.Printf("NewOAuthConfig Error! %v\n", err)
    }

    spt, sptErr := adal.NewServicePrincipalTokenFromUsernamePassword(*oauthConfig, clientID, username, password, resource)
    //spt, sptErr := adal.NewServicePrincipalTokenFromUsernamePassword(*oauthConfig, clientID, username, password, config.Resource)
    if sptErr != nil {
        fmt.Printf("sptErr: %v\n", sptErr)
    }
    fmt.Printf("spt: %v\n", spt)

    err = spt.Refresh()
    if err != nil {
        fmt.Printf("Refresh Error: %v\n", err)
    }

    oAuthToken := spt.OAuthToken()
    token := spt.Token()
    fmt.Printf("oAuthToken: %v\n", oAuthToken)
    fmt.Printf("token: %v\n", token)
    fmt.Printf("token.AccessToken : %v\n", token.AccessToken)
    fmt.Printf("token.RefreshToken: %v\n", token.RefreshToken)
    fmt.Printf("token.ExpiresIn   : %v\n", token.ExpiresIn)
    fmt.Printf("token.ExpiresOn   : %v\n", token.ExpiresOn)
    fmt.Printf("token.NotBefore   : %v\n", token.NotBefore)
    fmt.Printf("token.Resource    : %v\n", token.Resource)
    fmt.Printf("token.Type        : %v\n", token.Type)

    return token.AccessToken
}


func sendRequest() {

    token := getToken()
    fmt.Printf("--- token --- %s\n", token)

    client := &http.Client{}
    reqJson := "{\"param1\": \"abc\"}"
    req, _ := http.NewRequest("POST", apiUrl, bytes.NewBuffer([]byte(reqJson)))
    req.Header.Set("Content-Type" , "application/json")
    req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("### Error: %v\n", err)
    }
    defer resp.Body.Close()

    fmt.Printf("status : %d\n", resp.StatusCode)
    fmt.Printf("length : %d\n", resp.ContentLength)
    for k, v := range resp.Header {
        fmt.Printf("header %s = %v\n",k, v)
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("error: %T\n", err)
    }

    fmt.Printf("body: %v\n", string(body))

    // 取得したデータをローカルにファイル出力
    writeData(fmt.Sprintf("receive_data_%s", time.Now().Format("20060102_030405")), body)
}

func writeData(filename string, data []byte) error {
    file, err := os.Create(filename)
    if err != nil {
        return err 
    }   
    defer file.Close()

    _, err = file.Write(data)
    if err != nil {
        return err 
    }   
    return nil 
}

func main() {
    sendRequest()
}
}}

#html(</div>)

* 動作確認 [#eed7f41b]
#html(<div class="pl10">)
#TODO

#myterm2(){{
go run test.go
}}

#html(</div>)


トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS