Azure Data Lakeのエンドユーザー認証

Data Lakeに認証はAzure ADが必須で、結構はハマる人が多いようなので簡単に説明する。


まずは認証オプションだが**エンドユーザー認証**と**サービス間認証**の２種類が存在する。
https://docs.microsoft.com/ja-jp/azure/data-lake-store/data-lakes-store-authentication-using-azure-active-directory
 
エンドユーザー認証ではMFA、サービス間認証ではクライアント証明など利用可能だ。
![image](https://qiita-image-store.s3.amazonaws.com/0/33998/8d5a0e79-f248-e1e7-3c5b-31081c48e62a.png)


### エンドユーザー認証

さて、この記事のテーマであるエンドユーザー認証だが[Data Lake Store での Azure Active Directory を使用したエンドユーザーの認証
](https://docs.microsoft.com/ja-jp/azure/data-lake-store/data-lake-store-end-user-authenticate-using-active-directory)を参考にしてほしい。さらっと記載してある[こちらのリソースにアクセスできる Azure Active Directory アプリケーションとサービス プリンシパルをポータルで作成する
](https://docs.microsoft.com/ja-jp/azure/azure-resource-manager/resource-group-create-service-principal-portal)の手順も忘れないようにして欲しい。

Azure ADへのアプリの登録が完了すると次の画面が表示されApplication ID等の情報が取得できる。なお、Native ApplicationではこれがClient IDに対応する。
![image](https://qiita-image-store.s3.amazonaws.com/0/33998/7e837c55-fce0-84aa-d53d-f29917d863d8.png)

ちなみにネイティブアプリでは簡単のためにつぎの値をつかって簡単にアクセスできるようにもなっている。
ClientId : 1950a258-227b-4e31-a9cf-717495945fc2
RedirectUrl : urn: ietf: wg: oauth: 2.0:oob

また、テナントIDにはAzure Active DirectoryのDirectory IDをセットする。
![image](https://qiita-image-store.s3.amazonaws.com/0/33998/834ab39e-f95e-a359-09c6-f6e62994dce7.png)

管理用のコードはこんな感じ


```csharp
using System;
using System.Threading;
using System.IO;
using Microsoft.Rest.Azure.Authentication;
using Microsoft.Azure.Management.DataLake.Store;
using Microsoft.Azure.Management.DataLake.StoreUploader;
using Microsoft.Azure.Management.DataLake.Store.Models;
using System.Collections.Generic;
using System.Text;

namespace CreateADLApplication
{
    class Program
    {   
        private static DataLakeStoreAccountManagementClient _adlsClient;
        private static DataLakeStoreFileSystemManagementClient _adlsFileSystemClient;

        private static string _adlsAccountName;
        private static string _resourceGroupName;
        private static string _location;
        private static string _subId;

        private static void Main(string[] args)
        {
            _adlsAccountName = "[ACCOUNT NAME]"; // TODO: Replace this value with the name of your existing Data Lake Store account.
            _resourceGroupName = "[RESOURCE GROUP NAME]"; // TODO: Replace this value with the name of the resource group containing your Data Lake Store account.
            _location = "East US 2";
            _subId = [SUSBSCRIPTION_ID];

            string localFolderPath = @"C:\local_path"; // TODO: Make sure this exists and can be overwritten.
            string localFilePath = localFolderPath + "file.txt"; // TODO: Make sure this exists and can be overwritten.
            string remoteFolderPath = "/data_lake_path/";
            string remoteFilePath = remoteFolderPath + "file.txt";
            // 認証後のURLを指定。Azure ADのアプリ登録で設定したRedirect URIと一致
            string redirectURIs = "https://www.microsoft.com/";

            // User login via interactive popup
            // Use the client ID of an existing AAD "Native Client" application.
            SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
            var tenant_id = [TENANT ID];
            var nativeClientApp_clientId = [CLIENT ID];
            var activeDirectoryClientSettings = ActiveDirectoryClientSettings.UsePromptOnly(nativeClientApp_clientId, new Uri(redirectURIs));
            var creds = UserTokenProvider.LoginWithPromptAsync(tenant_id, activeDirectoryClientSettings).Result;


            // Create client objects and set the subscription ID
            _adlsClient = new DataLakeStoreAccountManagementClient(creds);
            _adlsFileSystemClient = new DataLakeStoreFileSystemManagementClient(creds);

            _adlsClient.SubscriptionId = _subId;

            foreach(DataLakeStoreAccount d in ListAdlStoreAccounts())
            {
                Console.WriteLine(d.Name);
            }

            foreach (FileStatusProperties d in ListItems("/Samples/Data"))
            {
                Console.WriteLine(d.Type);
            }

        }


        // List all ADLS accounts within the subscription
        public static List<DataLakeStoreAccount> ListAdlStoreAccounts()
        {
            var response = _adlsClient.Account.List();
            var accounts = new List<DataLakeStoreAccount>(response);

            while (response.NextPageLink != null)
            {
                response = _adlsClient.Account.ListNext(response.NextPageLink);
                accounts.AddRange(response);
            }

            return accounts;
        }

        // Create a directory
        public static void CreateDirectory(string path)
        {
            _adlsFileSystemClient.FileSystem.Mkdirs(_adlsAccountName, path);
        }

        // Upload a file
        public static void UploadFile(string srcFilePath, string destFilePath, bool force = true)
        {
            var parameters = new UploadParameters(srcFilePath, destFilePath, _adlsAccountName, isOverwrite: force);
            var frontend = new DataLakeStoreFrontEndAdapter(_adlsAccountName, _adlsFileSystemClient);
            var uploader = new DataLakeStoreUploader(parameters, frontend);
            uploader.Execute();
        }

        // Get file or directory info
        public static FileStatusProperties GetItemInfo(string path)
        {
            return _adlsFileSystemClient.FileSystem.GetFileStatus(_adlsAccountName, path).FileStatus;
        }


        public static List<FileStatusProperties> ListItems(string directoryPath)
        {
            return (List<FileStatusProperties>)_adlsFileSystemClient.FileSystem.ListFileStatus(_adlsAccountName, directoryPath).FileStatuses.FileStatus;
        }

        // Concatenate files
        public static void ConcatenateFiles(string[] srcFilePaths, string destFilePath)
        {
            _adlsFileSystemClient.FileSystem.Concat(_adlsAccountName, destFilePath, srcFilePaths);
        }

        // Append to file
        public static void AppendToFile(string path, string content)
        {
            var stream = new MemoryStream(Encoding.UTF8.GetBytes(content));

            _adlsFileSystemClient.FileSystem.Append(_adlsAccountName, path, stream);
        }

        // Download file
        public static void DownloadFile(string srcPath, string destPath)
        {
            var stream = _adlsFileSystemClient.FileSystem.Open(_adlsAccountName, srcPath);
            var fileStream = new FileStream(destPath, FileMode.Create);

            stream.CopyTo(fileStream);
            fileStream.Close();
            stream.Close();
        }
    }
}



```