Error rpc error code unauthenticated desc oauth token is invalid or expired

Deployment doesn’t work #1 Comments Trying to setup YF deployment. Here is how my workflow definition looks: But when I run it, I’m getting an error: The text was updated successfully, but these errors were encountered: Thanks for reaching out, will check it today! I missed pointing that you need to set env ENTRYPOINT […]

Содержание

  1. Deployment doesn’t work #1
  2. Comments
  3. Footer
  4. Name already in use
  5. complete-gRPC / lecture15_rus.md

Deployment doesn’t work #1

Trying to setup YF deployment. Here is how my workflow definition looks:

But when I run it, I’m getting an error:

The text was updated successfully, but these errors were encountered:

Thanks for reaching out, will check it today!

I missed pointing that you need to set env ENTRYPOINT
check it here https://github.com/Goodsmileduck/example-yandex-serverless-action/blob/master/.github/workflows/main.yml
just tested without settings ENTRYPOINT got same error.

README.md updated
drop a comment here once you got it fixed.

@Goodsmileduck I added ENTRYPOINT . The error is gone, but now I have another one:

ERROR: failed to find function with name «test123»: iam token create failed: rpc error: code = Unauthenticated desc = OAuth token is invalid or expired

Does it mean that I need IAM token instead of API token in Yandex Cloud?
If so, I have public and private key — where to place both of them?

Since it’s yc in docker container you need to set TOKEN with token for yc
check Initialization step 1
https://cloud.yandex.com/docs/cli/quickstart

Сurrent state of action is kind of workaround to make deployment pipeline, I hope to check api of functions to write more native pipeline action.

Understood. Yes, with user token it works.
Hope it will support service accounts in the future.
Thank you for assistance!

© 2023 GitHub, Inc.

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.

Источник

Name already in use

complete-gRPC / lecture15_rus.md

  • Go to file T
  • Go to line L
  • Copy path
  • Copy permalink

Copy raw contents

Copy raw contents

Реализуем gRPC перехватчик + JWT аутентификацию в Go

Привет всем, рад снова вас приветствовать на курсе по gRPC! Сегодня мы узнаем как использовать gRPC перехватчики для аутентификации и авторизации пользователей.

Что такое gRPC перехватчик?

Ну, по сути, он представляет собой связующую, промежуточную функцию, которую можно добавить как на стороне сервера, так и на стороне клиента. Серверный перехватчик — это функция, вызываемая gRPC сервером, перед тем как будет выполнен RPC метод. Её можно использовать для разных целей, например, логирования, трассировки, ограничения частоты запросов, аутентификации и авторизации. Точно также клиентский перехватчик — это функция, которая будет вызываться gRPC клиентом перед выполнением фактического RPC.

Рисунок 1 — gRPC перехватчик.

На этой лекции мы сначала реализуем серверный перехватчик для авторизации доступа к нашим gRPC API с помощью JSON веб-токена (JWT). Используя этот перехватчик, мы будем уверены, что некоторые API на нашем сервере смогут вызывать только пользователи с определенными ролями. Затем мы реализуем клиентский перехватчик для входа пользователя в систему и добавим JWT к запросу перед вызовом gRPC API.

Простой серверный перехватчик

Итак, давайте начнём с добавления простого перехватчика к нашему gRPC серверу. Перехватчики существуют двух типов: первые — для унарных RPC, а вторые — для потоковых RPC.

Давайте передадим новый параметр grpc.UnaryInterceptor() в эту функцию grpc.NewServer() .

Она ожидает на вход серверный унарный перехватчик. Мы можем нажать Command в macOS (Ctrl в Windows и Linux) и щелкнуть по имени функции, чтобы перейти к её определению. Давайте откроем таким способом определение UnaryServerInterceptor , скопируем сигнатуру этой функции и скопируем её в наш файл main.go . Я назову её unaryInterceptor() . У неё есть несколько входных параметров, таких как контекст, запрос, информация об унарном сервере и фактический унарный обработчик. Она возвращает ответ и ошибку. Теперь мы можем передать эту функцию в качестве параметра унарному перехватчику. Здесь нам нужно не забыть добавить название пакета grpc к структуре UnaryServerInfo и функции UnaryHandler .

Отлично, теперь давайте просто добавим простое сообщение в лог о том, что был вызван унарный перехватчик, добавив сюда полное название метода запрашиваемого RPC. Затем мы просто вызываем фактический обработчик с исходным контекстом и запросом и возвращаем его результат.

Мы можем сделать то же самое для потокового перехватчика. Добавьте параметр grpc.StreamInterceptor() . Найдите определение функции, чтобы получить её сигнатуру. Скопируйте и вставьте её в файл main.go . Передайте эту функцию в качестве параметра потоковому перехватчику. Добавим сообщение в лог с полным названием RPC метода. В этот раз мы вызываем обработчик с параметрами srv и stream .

Запускаем клиент и сервер

Давайте посмотрим как это работает! Сначала я стартую сервер, затем открою новую вкладку терминала и запущу клиент. Как видно из логов сервера, унарный перехватчик вызывается 3 раза для CreateLaptop RPC. Далее выводится полное название этого RPC: /techschool_pcbook.LaptopService/CreateLaptop , которое включает имя пакета techschool_pcbook и сервиса LaptopService .

Теперь введите «y», чтобы оценить 3 созданных ноутбука. Потоковый перехватчик вызывается единожды.

Итак, теперь у вас есть некоторое представление о том как работает серверный перехватчик. Мы расширим его функциональные возможности, чтобы использовать для аутентификации и авторизации запросов от пользователя. Для этого нам нужно добавить пользователей в нашу систему, а также сервис для входа пользователей в систему и возврата JWT токена доступа.

Итак, давайте создадим файл user.go и определим новую структуру User . Она будет состоять из имени пользователя, хэшированного пароля и роли. Мы добавим метод NewUser() для создания нового пользователя, который принимает на вход имя пользователя, пароль и роль и возвращает объект User и ошибку.

Мы никогда не должны хранить пароль в открытом виде в системе, поэтому здесь будем использовать bcrypt , чтобы сначала захэшировать пароль. Пока что будем передавать bcrypt.DefaultCost во второй аргумент функции GenerateFromPassword . Если возникает ошибка, просто обернём и вернём её. В противном случае мы создаём новый объект пользователя с именем, хэшированным паролем и ролью и возвращаем его. Затем мы определяем метод для проверки правильности пароля введенного пользователем. Для этого вызовем функцию bcrypt.CompareHashAndPassword() и передадим ей захэшированный и введенный пользователем пароль. Она вернёт true , если ошибка равна nil . Я добавлю сюда ещё один метод для клонирования пользователя. Эта функция понадобится нам позже, поскольку мы собираемся хранить пользователей в памяти.

Хранилище для пользователей

Отлично, теперь давайте создадим файл user_store.go и определим в нём интерфейс как мы это делали для хранилища ноутбуков и рейтингов в предыдущих лекциях. В нём определим два метода: первый — для сохранения пользователя в хранилище, а второй — для поиска пользователя в хранилище по имени. Теперь давайте реализуем этот интерфейс с помощью хранилища пользователей в памяти. Оно содержит мьютекс для управления доступом к ресурсу в многопоточном приложении и карту users , где ключом будет username . Я напишу функцию для создания нового хранилища пользователей в памяти и инициализирую карту users в ней.

Затем нам нужно реализовать методы Save и Find интерфейса. В методе Save мы сначала захватываем блокировку по записи, затем проверяем существует ли пользователь с таким именем в хранилище. Если «да» — возвращаем ошибку. В противном случае мы клонируем поступивший на вход объект user и помещаем его в карту.

Для метода Find захватываем блокировку по чтению, затем получаем пользователя по имени из карты. Если результат равен nil , просто возвращаем nil, nil . В противном случае — объект-клон этого пользователя.

На этом всё. Хранилище для пользователей готово.

Теперь давайте реализуем JWT менеджер, генерирующий и проверяющий токена доступа пользователей. Структура JWTManager состоит из двух полей: секретный ключ для подписи и проверки токена доступа и допустимый срок действия токена. Эти два поля должны быть переданы в качестве входных параметров в функцию NewJWTManager() .

Чтобы работать с JWT, я воспользуюсь библиотекой jwt-go . Давайте поищем её в браузере. Скопируйте ссылку библиотеки на Github https://github.com/dgrijalva/jwt-go и выполните в терминале

чтобы установить её. Отлично, теперь вернемся к нашему JWT менеджеру. JSON веб-токен должен содержать claims-объект, в котором находится некая полезная информация о пользователя, владеющим им. Таким образом, я объявлю свой, пользовательский UserClaims . Он будет включать в себя стандартный JWT claims-объект в виде анонимного поля. Этот стандартный claims-объект включает в себя некоторую полезную информацию и каждое из его полей мы могли бы проинициализировать. Но для демонстрационных целей я буду использовать только одно поле — expiresAt — срок действия токена. Как вы возможно заметили, claims-объект содержит метод Valid() , который автоматически проверяет, истек ли срок действия токена за нас. Он будет использоваться когда мы позже вызовем метод ParseWithClaims . Хорошо, теперь кроме этого стандартного claims-объекта, давайте добавим поле с именем пользователя и его ролью, поскольку мы хотим выполнять авторизацию на основе ролей.

Генерируем и подписываем токен доступа

Затем давайте напишем метод, генерирующий и подписывающий новый токен доступа для конкретного пользователя. В этом методе мы сначала создаём новый объект UserClaims . Из стандартных claims, я проинициализирую только поле expiresAt . Мы должны добавить время действия токена к текущему времени и преобразовать его в метку времени Unix. Затем мы инициализируем значения для полей Username и Role и вызываем функцию jwt.NewWithClaims() , чтобы создать объект-токен. Для простоты здесь я подписываю токен, используя HMAC алгоритм, а именно HS256 . Для продакшена вам следует применять более стойкие методы, например, RSA или алгоритмы цифровой подписи на эллиптических кривых. Последний и самый важный шаг — подписать сгенерированный токен своим секретным ключом. Это гарантирует, что никто не сможет подделать токен доступа, поскольку у них не будет вашего секретного ключа.

Разбираем и проверяем токен доступа

Здорово, теперь давайте добавим другой метод для проверки токена доступа и выдачи UserClaims , если токен действителен. Нам просто нужно вызвать jwt.ParseWithClaims передать в него токен доступа, пустой объект UserClaims и анонимную функцию, возвращающую ключ. В этой функции нужно прежде всего проверить, что метод, которым подписан токен, совпадает с алгоритмом, применяемым на сервере, в нашем случае HMAC . Если произошло совпадение, то мы просто возвращаем секретный ключ, который использовался для подписи токена. Функция jwt.ParseWithClaims вернет объект-токен и ошибку. Если ошибка не равна nil , то выдаём сообщение о некорректном токене. В противном случае получаем claims из токена и преобразуем их в объект UserClaims . Если преобразование осуществить не удалось, возвращаем ошибку о некорректных claims токена. Иначе просто возвращаем UserClaims . На этом всё!

Реализуем сервер службы аутентификации

Следующее, что нам нужно сделать — это предоставить клиенту новый сервис для входа в систему и получения токена доступа. Давайте создадим новый файл auth_service.proto . Название пакета и остальные настройки будут такими же, как и в других proto файлах. Мы зададим сообщение LoginRequest с двумя полями: username типа string и password типа string и сообщение LoginResponse с единственным полем: токеном доступа. Определим новый сервис AuthService . Он будет содержать только одну унарную RPC: Login , которая принимает на вход LoginRequest и возвращает LoginResponse .

Отлично, теперь давайте выполним команду make gen , чтобы сгенерировать код для этого сервиса. Как видите, были созданы файлы auth_service.pb.go и auth_service_grpc.pb.go . Как и в случае с сервером для ноутбуков в предыдущих лекциях, я создам новый файл auth_server.go для реализации этого нового сервиса. Структура AuthServer будет содержать userStore и JWTManager . Давайте добавим функцию для создания и выдачи нового объекта AuthServer .

Затем перейдём в файл auth_service_grpc.pb.go и скопируем сигнатуру функции Login . Вставим её в наш файл auth_server.go и сделаем методом структуры AuthServer . Этот метод очень легко реализовать. Сначала мы вызываем userStore.Find() , чтобы найти пользователя по имени. Если возникла ошибка, просто возвращаем её с кодом состояния Internal , иначе, если пользователь не найден или введён неверный пароль, выдаём ошибку с кодом состояния NotFound и сообщением о неверном имени пользователя или пароле. Если пользователь найден и пароль верен, то вызываем jwtManager.Generate() , чтобы сгенерировать новый токен доступа. Если произошла ошибка, возвращаем её с кодом состояния Internal . В противном случае создаём новый объект LoginResponse , используя сгенерированный токен доступа, и отправляем его клиенту.

Добавляем сервис аутентификации к gRPC серверу

Давайте добавим эту новый сервис аутентификации к gRPC серверу. Сначала нам нужно создать новое хранилище пользователей в памяти. Затем инициализируем новый JWT менеджер с секретным ключом и временем действия токена.

Для простоты я задам их здесь в виде констант.

На самом деле мы должны загружать их из переменных окружения или из файла конфигурации. Для демонстрационных целей установим время действия токена равным 15 минутам.

Затем нам нужно создать новый сервер аутентификации, используя userStore и jwtManager . Мы вызываем pb.RegisterAuthServiceServer , чтобы добавить его к gRPC серверу.

Чтобы протестировать новое API для входа в систему, мы должны добавить в неё нескольких пользователей. Давайте сделаем это. Я напишу функцию, которая создаст пользователя по заданному имени, паролю и роли и сохранит его в хранилище.

Затем в этой функции seedUsers() я вызову createUser() 2 раза, чтобы создать одного пользователя с правами администратора и одного обычного пользователя. Пусть у них будет один и тот же пароль — secret .

Теперь в функции main мы вызовем seedUsers() сразу после создания userStore .

Тестируем сервис аутентификации с помощью Evans CLI

Давайте протестируем его! Я запущу gRPC сервер. Затем используйте Evans для подключения к нему.

Когда мы вызываем show service , мы видим новый AuthService с Login RPC. Давайте выберем AuthService

и запустим Login RPC

Вводим имя пользователя admin1 . Попробуем отправить неверный пароль

Сервер возвращает неверное имя пользователя/пароль, как и ожидалось. Давайте снова вызовем Login , но в этот раз введём правильный пароль для admin1 .

Запрос выполнен успешно и мы получили токен доступа. Скопируем этот токен и перейдём на сайт jwt.io в браузере. Вставьте токен в текстовое поле Encoded . Мы видим в поле Decoded , что заголовок содержит алгоритм HS256 и тип токена JWT. Полезная нагрузка содержит claims пользователя с временем действия токена, именем пользователя и ролью. Итак, RPC для входа пользователя в систему работает отлично.

Тем не менее, мы ещё не написали соответствующий перехватчик для проверки токена. Итак, вернемся к коду и сделаем это.

Реализуем серверный перехватчик аутентификации

Я создам новый файл auth_interceptor.go и определю внутри него новую структуру AuthInterceptor .

Этот перехватчик будет содержать JWT менеджер и карту, определяющая для каждого RPC метода список ролей, которые могут получить к нему доступ. Таким образом, ключом карты будет полное название метода, а её значением — срез из названий ролей. Давайте напишем функцию NewAuthInterceptor() для создания и возврата нового объекта-перехватчика аутентификации. jwtManager и карта accessibleRoles будут входными параметрами этой функции.

Теперь я добавлю новый метод Unary() к объекту-перехватчику аутентификации, который создаст и вернет функцию для gRPC серверного унарного перехватчика.

Давайте откроем файл main.go , скопируем функцию unaryInterceptor() , которую мы написали ранее и вставим её в эту функцию Unary() . Эту анонимную функцию нам и надо вернуть.

Точно так же мы добавляем новый метод Stream() , который создаст и вернёт функцию для gRPC серверного потокового перехватчика. Скопируйте и вставьте функцию потокового перехватчика сюда из файла main.go .

Теперь в файле main.go мы должны создать новый объект-перехватчик, используя jwtManager и карту accessibleRoles .

Поскольку наш проект является учебным я просто напишу функцию, которая будет возвращать константную карту.

Затем в функцию grpc.NewServer() мы можем передать interceptor.Unary() и interceptor.Stream() .

Определяем доступные роли

Теперь для функции accessibleRoles нам нужно подготовить список RPC методов и ролей, которые могут получить доступ к каждому из них. Чтобы получить полное название RPC метода, давайте откроем терминал и выполним

Тогда в логах сервера мы увидим полное название метода CreateLaptop RPC: /techschool_pcbook.LaptopService/CreateLaptop . Давайте скопируем его. Мы знаем, что все методы LaptopService будут начинаться одинаково, поэтому я определю здесь константу. Затем мы создаём и возвращаем карту следующим образом.

Первый метод — это CreateLaptop , который могут вызывать только пользователи с правами admin . Метод UploadImage также доступен только для них. Метод RateLaptop могут вызывать как пользователи с правами admin , так и user . Пусть SearchLaptop API доступна всем, даже не зарегистрированным пользователям. Идея такова: мы не добавляем в эту карту SearchLaptop или любые другие общедоступные RPC.

Итак, давайте вернемся к перехватчику аутентификации. Мы определим новую функцию authorize() , которая на вход будет принимать контекст и метод и возвращать ошибку, если запрос не авторизирован.

Затем в функции Unary() мы вызываем interceptor.authorize() , передавая контекст и info.FullMethod . Если ошибка не равна nil , мы сразу выходим из функции.

Подобным образом, для функции Stream() мы вызываем interceptor.authorize() с контекстом потока и info.FullMethod и сразу же выходим из неё, если возникла ошибка.

Реализуем функцию authorize

Теперь давайте реализуем функцию authorize() . Сначала мы получаем список ролей, которые могут получить доступ к конкретному RPC методу. Если его нет в карту, это означает, что RPC публично доступен. Поэтому в этом случае мы просто возвращаем nil . В противном случае мы должны получить токен доступа из контекста. Для этого мы используем пакет grpc/metadata . Мы вызываем metadata.FromIncomingContext , чтобы получить метаданные запроса. Если их нет, то мы возвращаем ошибку с кодом состояния Unauthenticated . В противном случае мы получаем значения из метаданных по ключу «authorization». Если он пуст, выдаём ошибку с кодом состояния Unauthenticated , потому что отсутствует токен. Иначе токен доступа должен храниться в первом элементе полученного массива. Затем вызываем jwtManager.Verify , чтобы проверить токен и извлечь claims. Если возникла ошибка, это означает, что токен недействителен. Поэтому мы просто возвращаем клиенту код Unauthenticated . В противном случае мы перебираем в цикле accessibleRoles и проверяем может ли данный пользователь, учитывая его роль, получить доступ к этой RPC. Если роль пользователя найдена в списке, мы просто возвращаем nil . Если нет, мы возвращаем ошибку с кодом состояния PermissionDenied и сообщение о том, что у пользователя нет прав для доступа к этому RPC. На этом реализация серверного перехватчика авторизации завершена!

Давайте протестируем его работу в терминале. Сначала запустите сервер

Мы получили ошибку с кодом Unauthenticated

и текстом «authorization token is not provided». Это было ожидаемо, поскольку мы ещё не вошли в систему и не добавили токен доступа к запросу на стороне клиента.

Итак, давайте сделаем это!

Реализуем клиент сервиса аутентификации

Поскольку кода клиента становится всё больше, я создам отдельный пакет client для него. Затем создам новый файл auth_client.go внутри этой папки. Давайте определим структуру AuthClient для вызова сервиса аутентификации. Эта структура будет содержать поле service типа AuthServiceClient , который генерирует protoc , а также поля username и password , используемые для входа в систему и получения токена доступа.

Как обычно, мы определяем функцию для создания и возврата нового объекта-клиента для аутентификации. Она будет иметь три входных параметра: соединение с grpc клиентом, имя пользователя и пароль. Сервис будет создан путём вызова функции pb.NewAuthServiceClient() и передачи в неё соединения.

Затем мы пишем функцию Login для вызова Login RPC, чтобы получить токен доступа. Как и для других RPC, мы создаём контекст с таймаутом в 5 секунд, вызываем defer cancel() . Затем инициализируем запрос на вход с предоставленным именем пользователя и паролем и вызываем service.Login , используя этот запрос. Если ошибка не равна nil , мы просто возвращаем её. В противном случае мы выдаём полученный токен доступа вызывающей стороне. Клиент для аутентификации готов.

Реализуем клиентский перехватчик

Теперь давайте научимся создавать клиентский перехватчик. Я создам новый файл auth_interceptor.go в пакете client . Идея такова: мы будем перехватывать все gRPC запросы и прикреплять к ним токен доступа (при необходимости) перед вызовом сервера. По аналогии с тем, что мы делали на сервере я определю структуру AuthInterceptor . Она будет содержать объект-клиент для аутентификации, который будет использоваться для входа пользователя в систему, карту, указывающую для какого метода требуется аутентификация, и последний полученный токен доступа. Что значит «последний»? На самом деле мы создадим отдельную горутину, которая будет периодически вызывать API для входа в систему, чтобы получить новый токен доступа до истечения срока действия текущего.

Таким образом в функции NewAuthInterceptor() , помимо клиента и методов аутентификации, там также нужен параметр, определяющий время обновления токена. Оно укажет насколько часто нам нужно будет вызывать API для входа в систему, чтобы получить новый токен. В этой функции сначала мы создаём новый объект-перехватчик. Затем обращаемся к scheduleRefreshToken , чтобы запланировать обновление токена доступа и передаём в неё время после которого необходимо осуществить обновление. Если возникает ошибка, просто верните её, иначе возвращаем перехватчик.

Настраиваем обновление токена по графику

Теперь давайте реализуем функцию scheduleRefreshToken . Но сначала нам нужна функция для обновления токена без планирования. В этой функции, мы просто используем клиент аутентификации для входа в систему. После возврата токена мы просто сохраняем его в поле interceptor.accessToken . Давайте добавим сюда простой лог, чтобы было проще зафиксировать факт обновления токена, и затем вернём nil .

Теперь в функции scheduleRefreshToken() мы должны убедиться, что первый вызов refreshToken() прошёл успешно, то есть правильный токен всегда доступен для использования. После этого мы запускаем новую горутину. Здесь я использую переменную wait , в которой сохраняю промежуток времени до следующего обновления токена. Затем в бесконечном цикле вызываем time.Sleep , чтобы организовать задержку, и, дождавшись необходимого момента времени, обращаемся к interceptor.refreshToken() . Если возникла ошибка, уменьшим период ожидания до, скажем, 1 секунды, прежде чем повторить попытку. Если все прошло без ошибок, то нам определенно стоит дождаться следующего периода обновления. Мы реализовали функцию, осуществляющую периодическое обновление токена.

Присоединяем токен к контексту запроса

Далее следует важная часть: добавление перехватчиков для присоединения токена к контексту запроса. Как и на стороне сервера, на этот раз мы определяем функцию Unary() , которая возвращает gRPC клиентский унарный перехватчик. Давайте посмотрим на этот фрагмент с grpc.UnaryClientInterceptor , чтобы увидеть как должна выглядеть функция перехватчика.

Я скопирую её сигнатуру и вставлю в файл auth_interceptor.go .

Эта функция, которую мы должны вернуть. Я немного переформатирую её и добавлю отсутствующий пакет grpc .

Теперь внутри этой функции-перехватчика давайте добавим простое сообщение в лог с названием вызывающего метода. Затем проверим нужна ли для этого метода аутентификация. Если «да», то мы должны присоединить токен доступа к контексту перед выполнением фактического RPC.

Итак, я определю новую функцию для присоединения токена к входному контексту и возврата результата. В этой функции мы просто используем metadata.AppendToOutgoingContext() , передавая входной контекст вместе с ключом «authorization» и значением токена доступа. Убедитесь, что ключ-строка «authorization» совпадает с той, которую мы использовали на стороне сервера.

Теперь вернемся к нашему унарному перехватчику. Если метод не требует аутентификации, то ничего делать не нужно, просто выполняем RPC с первоначальным контекстом.

Аналогичным образом можно реализовать потоковый перехватчик. Скопируйте сигнатуру функции grpc.StreamClientInterceptor , вставьте её в файл auth_interceptor.go , допишите return , отформатируйте код и добавьте отсутствующее название пакета grpc .

Затем пишем сообщение в лог, проверяем требует ли метод аутентификации. Если «да», вызываем streamer с контекстом, к которому был присоединен токен доступа или просто вызовите streamer с первоначальным. На этом мы закончили реализацию клиентского перехватчика для аутентификации.

Проводим рефакторинг gRPC клиента

Теперь откроем файл cmd/client/main.go . Прежде чем добавить перехватчики к клиенту я осуществлю небольшой рефакторинг. Давайте вынесем эту функции createLaptop , searchLaptop , uploadImage , rateLaptop в отдельный файл внутри нового пакета client . В этом файле давайте определим структуру LaptopClient .

Он будет состоять из объекта LaptopServiceClient . Затем, как обычно, мы определяем функцию для создания нового объекта-клиента. Он принимает на вход клиентское соединение и используется его для создания нового клиента, осуществляющего операции с ноутбуками.

Теперь мы должны превратить функцию createLaptop в метод объекта LaptopClient и сделать его публичным, сделав первую букву C заглавной. Также добавьте .service , чтобы исправить ошибку.

Затем осуществляем аналогичные операции для функции searchLaptop , uploadImage и наконец rateLaptop .

Всё готово. Теперь давайте вернёмся к файлу cmd/client/main.go . Мы должны изменить pb.LaptopServiceClient на client.LaptopClient , затем вызвать laptopClient.CreateLaptop . То же самое делаем для всех остальных функций тестирующих работу сервера.

Добавляем перехватчик аутентификации клиенту

Теперь в функции main мы должны вызвать client.NewLaptopClient() и передать в него gRPC соединение. Здесь не всё так просто — нам нужно отдельное соединение для клиента сервиса аутентификации authClient , так как он будет использоваться для создания перехватчика аутентификации interceptor . interceptor в свою очередь будет применяться для инициализации другого соединения с клиентом, осуществляющим работу с ноутбуками. Поэтому я изменил название соединения на cc1 и создал новый клиент аутентификации с помощью него.

Для упрощения я задам username и password в виде констант.

Затем давайте создадим новый перехватчик с клиентом сервиса аутентификации. Период обновления также будет константой. Пусть в нашем случае мы будем обновлять токен каждые 30 секунд.

Нам также нужна функция для определения списка методов, требующих аутентификации. Я просто скопирую и вставлю их из серверного перехватчика. Изменим map[string][]string на map[string]bool , а все значения на true .

Отлично, вернемся к функции main . Если во время вызова client.NewAuthInterceptor возникла ошибка, мы пишем её в лог и аварийно завершаем работу. Если нет, то пытаемся создать другое соединение, но в этот раз с двумя дополнительными параметрами: унарным и потоковым перехватчиком. Затем мы меняем здесь client.NewLaptopClient(cc2) название этого соединения на cc2 . Реализация клиента завершена.

Тестируем клиентский перехватчик аутентификации

Откроем терминал и протестируем работу. Сначала запустите сервер

Появилось странное сообщение: «client is up to date». Оно связано с тем, что команда «make» спутала нашу папку client с командой client . Чтобы исправить это, добавим её в список PHONY файла Makefile . Давайте я добавлю все эти команды в список PHONY.

Вернитесь в терминал и снова выполните make client . На этот раз мы увидим сообщения «token refreshed» и «unary interceptor» в логах, а также информацию о том, что было успешно создано 3 ноутбука.

Давайте введём «y», чтобы оценить их. Операция прошла успешно, и мы видим сообщение в логе от потокового перехватчика.

На стороне сервера также выводятся сообщения от унарных и потоковых перехватчиков.

Через какое-то время на стороне клиента мы увидим, что токен обновился. И, наконец, давайте изменим имя пользователя на user1

And after a while, on the client side, we will see that the token is getting refreshed as well. Before we finish let’s change this username to user1

и посмотрим, что произойдёт. Как и следовало ожидать, мы получили ошибку с отказом в доступе

так как только пользователь с правами администратора может вызывать CreateLaptop API. Таким образом, всё работает как надо. Превосходно! На этом закончим сегодняшнюю лекцию. Надеюсь вам она понравилась. Спасибо за время, потраченное на чтение, и до новых встреч.

Источник

Содержание

  1. У кого-нибудь были проблемы с OAuth-токеном в Terraform? Система просто
  2. 6 ответов
  3. Похожие вопросы
  4. Deployment doesn’t work about yandex-serverless-action HOT 6 CLOSED
  5. Comments (6)
  6. Related Issues (11)
  7. Recommend Projects
  8. React
  9. Vue.js
  10. Typescript
  11. TensorFlow
  12. Django
  13. Laravel
  14. Recommend Topics
  15. javascript
  16. server
  17. Machine learning
  18. Visualization
  19. Recommend Org
  20. Facebook
  21. Microsoft
  22. Not working terraformer yandex cloud #565
  23. Comments
  24. Iam token create failed rpc error code unauthenticated desc oauth token is invalid or expired

У кого-нибудь были проблемы с OAuth-токеном в Terraform? Система просто

перестала принимать токен, при этом CLI его принимает, а попытка его обновить приводит к получению того же самого токена.

6 ответов

А у поддержки лапки.

дебаг в терраформе ничего интересного не показал?

А как использовать?

Error: Error while requesting API to create Yandex Cloud Container: *********************** rpc error: code = Unauthenticated desc = OAuth token is invalid or expired

Похожие вопросы

Привет! Вопрос не от разработчика, а от предпринимателя принимается сообществом к рассмотрению?

Мы в скором времени должны приступить к созданию SPA на React.js и Node.js. Сейчас имеем сервер в Yandex Cloud, на Ubuntu 22.04, с Node.js и React,js. А также купленный домен.

А на стороне реакта, и сервера, внутри, нужно что-то указывать?

Как сейчас сделать так, чтобы именно содержимое этой папки было доступно пользователю, когда он набирал домен в строке своей?

расскажите, пожалуйста, когда вертикальное масштабирование не справляется? условно, нужна машина 96 ядер, 576 рам, 8192 хдд, такая штука обойдётся в 210 тыс. рублей в месяц, т.

Кому-нибудь нужна бесплатная подписка Яндекс плюс на 2 месяца? Пишите в лс. Каждому лично дам собственный промокод одноразовый.

А никаких проблем с доступом до машин нет? По ssh за 3 минуты появилась только надпись using name, сам сайт на машине не виден.

Добрый день! А приходилось ли кому нибудь настраивать VPN туннель до сервиса в кубере?

Коллеги, а нет ли сейчас аварий с влиянием на Managed Service for Kafka ? (Версия 3.0) что то кластер не создаётся с настройками по умолчанию, сразу доступность — Dead

Вы все правильно пишите. Я не спорю. Я лишь подумал может у кого есть подобная проблема и решил ее. Или у кого то нет таких проблем и надо общаться с админами моими. Просто к.

Источник

Deployment doesn’t work about yandex-serverless-action HOT 6 CLOSED

Thanks for reaching out, will check it today!

Goodsmileduck commented on January 15, 2023

I missed pointing that you need to set env ENTRYPOINT
check it here https://github.com/Goodsmileduck/example-yandex-serverless-action/blob/master/.github/workflows/main.yml
just tested without settings ENTRYPOINT got same error.

README.md updated
drop a comment here once you got it fixed.

sergeyzwezdin commented on January 15, 2023

@Goodsmileduck I added ENTRYPOINT . The error is gone, but now I have another one:

ERROR: failed to find function with name «test123»: iam token create failed: rpc error: code = Unauthenticated desc = OAuth token is invalid or expired

Does it mean that I need IAM token instead of API token in Yandex Cloud?
If so, I have public and private key — where to place both of them?

Goodsmileduck commented on January 15, 2023

Since it’s yc in docker container you need to set TOKEN with token for yc
check Initialization step 1
https://cloud.yandex.com/docs/cli/quickstart

Goodsmileduck commented on January 15, 2023

Сurrent state of action is kind of workaround to make deployment pipeline, I hope to check api of functions to write more native pipeline action.

sergeyzwezdin commented on January 15, 2023

Understood. Yes, with user token it works.
Hope it will support service accounts in the future.
Thank you for assistance!

  • Feature request: add service account option HOT 1
  • More info about exclude HOT 2
  • Error if environment not passed HOT 1
  • Feature request: Add ignore pattern
  • [Feature Request] возможность не «exclude файлы из сборки», а наоборот «include только нужное» HOT 1
  • [Enhancement] Add link to allowed environment
  • Feature request: Update env variables of cloud function HOT 10
  • ERROR: zip archive content exceeds the maximum size 3.5 MB, use object storage to upload the content HOT 2
  • The action doesn’t cleanup after deployment HOT 4
  • Fail during initialization HOT 2

Recommend Projects

React

A declarative, efficient, and flexible JavaScript library for building user interfaces.

Vue.js

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

Typescript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

TensorFlow

An Open Source Machine Learning Framework for Everyone

Django

The Web framework for perfectionists with deadlines.

Laravel

A PHP framework for web artisans

Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

javascript

JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

Some thing interesting about web. New door for the world.

server

A server is a program made to process requests and deliver data to clients.

Machine learning

Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

Visualization

Some thing interesting about visualization, use data art

Some thing interesting about game, make everyone happy.

Recommend Org

Facebook

We are working to build community through open source technology. NB: members must have two-factor auth.

Microsoft

Open source projects and samples from Microsoft.

Источник

Not working terraformer yandex cloud #565

Hello! I builded terraformer from source (master branch) with support yandex provider

I created init file init.tf with content

I exported YC_TOKEN and YC_FOLDER_ID
Terraformer version

And i try import instance resource according this instruction https://github.com/GoogleCloudPlatform/terraformer#use-with-yandex and i get strange message

The text was updated successfully, but these errors were encountered:

Try go run build/main.go yandex

Yes, terraformer success builded. But now other error

And now message

With these envs i run other go program and all fine. I guess cause at this place (env only YC_TOKEN but not YC_FOLDER_ID)
https://github.com/GoogleCloudPlatform/terraformer/pull/563/files#diff-2326e26fda26c8cd9b8a7c49acad9899R31

I’m getting exactly the same error. Both YC_FOLDER_ID and YC_TOKEN are exported but running
./terraformer-yandex import yandex -r subnet gives

This is under WSL1 if this matters.
Any idea what’s going on here?

Tested on macOS and Linux with the same results, so it’s not WSL1 related.

@diversys Hi!
There is an error in the documentation 🙁
I just checked and the folder_id parameter should be set like this:

Thus, the YC_FOLDER_ID environment variable does not affect anything.

Thanks @GennadySpb! With this I got a bit further now. However now it complains about a token:

Any idea what could be wrong?

I think I know a problem that could lead to this (requires a go-sdk update). I will try to fix/PR optimistically today.

@diversys Please build and try terraformer from #1259 for your case.

@GennadySpb turned out it is not possible to use OAuth token for Yandex Cloud federation account I use and service account key file should be used instead.
Is it possible to use service account key file with terraformer?

I’ve just built terraformer from master (right after your PR was merged), created fresh iam token and exported it as YC_TOKEN env var and got the same error:
err: iam token create failed: rpc error: code = Unauthenticated desc = OAuth token is invalid or expired

So, the current authentication method in Terraformer supports only OAuth.
After #1263, all methods should be available, as in terraform-provider-yandex.

Very cool! I’m going to try that now and report back.

However, reading the diff I should be getting this message, right?:
one of ‘YC_TOKEN’ or ‘YC_SERVICE_ACCOUNT_KEY_FILE’ env variable should be specified;

But this is not the case here.

I can’t reproduce it, sorry. Just checked all supported authentication methods using the latest version of terraformer v0.8.19.

A few comments about the places that can lead to an error:

to create SA key use command like
yc iam key create —service-account-id ajeqpggm78fl9qqqqqqq -o sa_key.json
You will get a SA key file in json format that can be used with terraformer.

check validity of token ( yc —profile=default iam create-token ) by yc CLI tool before use with terraformer.
YC_IAM_TOKEN= yc compute instance list

I’m using the latest v0.8.19.

yc iam key create —service-account-id ajeqpggm78fl9qqqqqqq -o sa_key.json
You will get a SA key file in json format that can be used with terraformer.

I’ve just created it using your command.

  1. check validity of token ( yc —profile=default iam create-token ) by yc CLI tool before use with terraformer.
    YC_IAM_TOKEN= yc compute instance list

This does list instances just fine but errors out with:

Running terraformer without YC_TOKEN or YC_SERVICE_ACCOUNT_KEY_FILE never reaches this line:

Источник

Iam token create failed rpc error code unauthenticated desc oauth token is invalid or expired

Hello! I builded terraformer from source (master branch) with support yandex provider

I created init file init.tf with content

I exported YC_TOKEN and YC_FOLDER_ID
Terraformer version

And i try import instance resource according this instruction https://github.com/GoogleCloudPlatform/terraformer#use-with-yandex and i get strange message

Created at 7 months ago

Try go run build/main.go yandex

Created at 2 years ago

Yes, terraformer success builded. But now other error

And now message

With these envs i run other go program and all fine. I guess cause at this place (env only YC_TOKEN but not YC_FOLDER_ID)
https://github.com/GoogleCloudPlatform/terraformer/pull/563/files#diff-2326e26fda26c8cd9b8a7c49acad9899R31

Created at 2 years ago

I’m getting exactly the same error. Both YC_FOLDER_ID and YC_TOKEN are exported but running
./terraformer-yandex import yandex -r subnet gives

This is under WSL1 if this matters.
Any idea what’s going on here?

Created at 10 months ago

Tested on macOS and Linux with the same results, so it’s not WSL1 related.

Created at 10 months ago

Created at 10 months ago

@diversys Hi!
There is an error in the documentation 🙁
I just checked and the folder_id parameter should be set like this:

Thus, the YC_FOLDER_ID environment variable does not affect anything.

Created at 10 months ago

Thanks @GennadySpb! With this I got a bit further now. However now it complains about a token:

Any idea what could be wrong?

Created at 9 months ago

I think I know a problem that could lead to this (requires a go-sdk update). I will try to fix/PR optimistically today.

Created at 9 months ago

@diversys Please build and try terraformer from #1259 for your case.

Created at 9 months ago

@GennadySpb turned out it is not possible to use OAuth token for Yandex Cloud federation account I use and service account key file should be used instead.
Is it possible to use service account key file with terraformer?

Created at 9 months ago

I’ve just built terraformer from master (right after your PR was merged), created fresh iam token and exported it as YC_TOKEN env var and got the same error:
err: iam token create failed: rpc error: code = Unauthenticated desc = OAuth token is invalid or expired

Created at 9 months ago

So, the current authentication method in Terraformer supports only OAuth.
After #1263, all methods should be available, as in terraform-provider-yandex.

Created at 9 months ago

Very cool! I’m going to try that now and report back.

Created at 9 months ago

However, reading the diff I should be getting this message, right?:
one of ‘YC_TOKEN’ or ‘YC_SERVICE_ACCOUNT_KEY_FILE’ env variable should be specified;

But this is not the case here.

Created at 7 months ago

Created at 9 months ago

I can’t reproduce it, sorry. Just checked all supported authentication methods using the latest version of terraformer v0.8.19.

A few comments about the places that can lead to an error:

to create SA key use command like
yc iam key create —service-account-id ajeqpggm78fl9qqqqqqq -o sa_key.json
You will get a SA key file in json format that can be used with terraformer.

check validity of token ( yc —profile=default iam create-token ) by yc CLI tool before use with terraformer.
YC_IAM_TOKEN= yc compute instance list

Created at 9 months ago

I’m using the latest v0.8.19.

yc iam key create —service-account-id ajeqpggm78fl9qqqqqqq -o sa_key.json
You will get a SA key file in json format that can be used with terraformer.

I’ve just created it using your command.

  1. check validity of token ( yc —profile=default iam create-token ) by yc CLI tool before use with terraformer.
    YC_IAM_TOKEN= yc compute instance list

This does list instances just fine but errors out with:

Running terraformer without YC_TOKEN or YC_SERVICE_ACCOUNT_KEY_FILE never reaches this line:

return nil , fmt . Errorf ( «one of ‘YC_TOKEN’ or ‘YC_SERVICE_ACCOUNT_KEY_FILE’ env variable should be specified; if you are inside compute instance, you can attach service account to it in order to authenticate via instance service account» )

Thanks for your help so far!

Created at 9 months ago

Running terraformer without YC_TOKEN or YC_SERVICE_ACCOUNT_KEY_FILE never reaches this line:

return nil , fmt . Errorf ( «one of ‘YC_TOKEN’ or ‘YC_SERVICE_ACCOUNT_KEY_FILE’ env variable should be specified; if you are inside compute instance, you can attach service account to it in order to authenticate via instance service account» )

This is very strange. Check your environment (env vars) before run terraformer. Or just unset both vars before run:

Created at 9 months ago

Of course, they are unset. Anything I can add to the code to help with debugging? I can build stuff, but I have zero knowledge of Go, tho.

Created at 9 months ago

So from strace output it doesn’t seem terraformer even attempts to open sa_key.json

strace terraformer import yandex -r subnet —folder_ids b1gg5ic4o9tlkb64j21k 2>&1 | grep open

Источник

Котяй-Негодяй

перестала принимать токен, при этом CLI его принимает, а попытка его обновить приводит к получению того же самого токена.

russian

software

database

yandex-cloud

14:56 29.03.2022


6

ответов

А у поддержки лапки.

14:57 29.03.2022

дебаг в терраформе ничего интересного не показал?

14:57 29.03.2022

че пишет-то?

14:59 29.03.2022

А как использовать?

14:59 29.03.2022


Nikolay 🤦‍♂️ Matrosov

че пишет-то?

Error: Error while requesting API to create Yandex Cloud Container: *********************** rpc error: code = Unauthenticated desc = OAuth token is invalid or expired

15:00 29.03.2022


Котяй Негодяй

А как использовать?

https://www.terraform.io/internals/debugging

15:01 29.03.2022

Похожие вопросы

Понравилась статья? Поделить с друзьями:
  • Error router requires newer winbox please upgrade что делать
  • Error round was not declared in this scope
  • Error root internal python error in the inspect module
  • Error room айзек
  • Error rom file size incorrect