diff --git a/.appveyor/appveyor.yml b/.appveyor/appveyor.yml
index 50849831f..391c75eaf 100644
--- a/.appveyor/appveyor.yml
+++ b/.appveyor/appveyor.yml
@@ -7,8 +7,8 @@ environment:
secure: 3kWTz99Qj+ipyaR73CxcJeGRRbmk84MF2ERDu6MyY10cjHAi6s3AVZ2Ccoa+Ioyt
appName: saml2aws
install:
-- set PATH=C:\msys64\mingw64\bin;C:\go118\bin;%PATH%
-- set GOROOT=C:\go118
+- set PATH=C:\msys64\mingw64\bin;C:\go120\bin;%PATH%
+- set GOROOT=C:\go120
- ps: >-
$VerbosePreference = 'Continue'
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..6162e9cc4
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+.buildtemp
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 1bb13ea22..1e0337155 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -6,3 +6,9 @@ updates:
interval: "weekly"
labels:
- "type: dependencies"
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ labels:
+ - "type: dependencies"
diff --git a/.github/win-msi/out/.gitignore b/.github/win-msi/out/.gitignore
new file mode 100644
index 000000000..1287e9bd7
--- /dev/null
+++ b/.github/win-msi/out/.gitignore
@@ -0,0 +1,2 @@
+**
+!.gitignore
diff --git a/.github/win-msi/src/saml2aws.wxs b/.github/win-msi/src/saml2aws.wxs
new file mode 100644
index 000000000..f1b2c8571
--- /dev/null
+++ b/.github/win-msi/src/saml2aws.wxs
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.github/win-msi/wix.sh b/.github/win-msi/wix.sh
new file mode 100644
index 000000000..cbf8dc092
--- /dev/null
+++ b/.github/win-msi/wix.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+candle src/saml2aws.wxs -dSaml2AwsVer=${VERSION} -o "out/"
+light -sval "out/saml2aws.wixobj" -o "out/saml2aws_${VERSION}_windows_amd64.msi"
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 024ac5ec9..e7b2891b9 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -2,12 +2,11 @@ name: Go
on:
push:
- branches: [ master ]
+ branches: [master]
pull_request:
- branches: [ master ]
+ branches: [master]
jobs:
-
build:
name: Build
runs-on: ${{ matrix.os }}
@@ -15,54 +14,97 @@ jobs:
matrix:
os: [ubuntu-latest, macOS-latest, macos-11]
steps:
+ - name: Set up Go 1.x
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.20.x
- - name: Set up Go 1.x
- uses: actions/setup-go@v2
- with:
- go-version: 1.18.x
+ - name: Check out code into the Go module directory
+ uses: actions/checkout@v3
- - name: Check out code into the Go module directory
- uses: actions/checkout@v2
+ - name: Test
+ run: |
+ go test -v ./... -coverprofile=${{ matrix.os }}_coverage.txt -covermode=atomic
- - name: Test
- run: go test -v ./...
+ - name: Upload coverage report
+ uses: actions/upload-artifact@v3
+ with:
+ name: reports
+ path: ${{ matrix.os }}_coverage.txt
+ if-no-files-found: error
+ retention-days: 1
- - name: Install
- run: go install ./cmd/saml2aws
+ - name: Install
+ run: go install ./cmd/saml2aws
linting:
name: lint
runs-on: ubuntu-latest
steps:
+ - name: Set up Go 1.x
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.20.x
- - name: Set up Go 1.x
- uses: actions/setup-go@v2
- with:
- go-version: 1.18.x
+ - name: Check out code into the Go module directory
+ uses: actions/checkout@v3
- - name: Check out code into the Go module directory
- uses: actions/checkout@v2
+ - name: golangci-lint
+ uses: golangci/golangci-lint-action@v3
+ with:
+ version: v1.53.2
+ args: --timeout=2m
- - name: golangci-lint
- uses: golangci/golangci-lint-action@v2
- with:
- version: v1.45.2
+ coverage:
+ name: coverage
+ permissions:
+ contents: read
+ runs-on: ubuntu-latest
+ needs: [build]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Download coverage reports
+ uses: actions/download-artifact@v3
+ with:
+ name: reports
+ path: reports
+
+ - name: Codecov
+ uses: codecov/codecov-action@v3
+ with:
+ directory: reports
+ flags: unittests
release-build:
name: release-build
- runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+ - ubuntu-20.04
+ - macos-latest
+ runs-on: ${{ matrix.os }}
steps:
+ - name: Set up Go 1.x
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.20.x
+
+ - name: Check out code into the Go module directory
+ uses: actions/checkout@v3
- - name: Set up Go 1.x
- uses: actions/setup-go@v2
- with:
- go-version: 1.18.x
+ - name: Install dependency required for linux builds
+ if: matrix.os == 'ubuntu-20.04'
+ run: sudo apt-get update && sudo apt-get install -y libudev-dev
- - name: Check out code into the Go module directory
- uses: actions/checkout@v2
+ - name: GoReleaser
+ uses: goreleaser/goreleaser-action@v4
+ with:
+ version: latest
+ args: build --snapshot --clean --config .goreleaser.${{ matrix.os }}.yml
- - name: GoReleaser
- uses: goreleaser/goreleaser-action@v2
- with:
- version: latest
- args: build --snapshot --rm-dist
+ - name: Upload
+ uses: actions/upload-artifact@v3
+ with:
+ name: saml2aws
+ path: dist/
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index be7f776f2..a8c25e48f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -4,25 +4,113 @@ on:
push:
tags:
- '*'
+ workflow_dispatch:
+ inputs:
+ tag:
+ description: The tag to run against. This trigger only runs the MSI builder.
+ required: true
jobs:
release:
name: release
- runs-on: macOS-latest
+ strategy:
+ # the goreleaser and the Github release API doesn't handle concurrent
+ # access well, so run goreleaser serially
+ max-parallel: 1
+ matrix:
+ os:
+ - ubuntu-latest
+ - ubuntu-20.04
+ - macos-latest
+ runs-on: ${{ matrix.os }}
+ if: github.event_name != 'workflow_dispatch'
+ permissions: write-all
steps:
- name: Set up Go 1.x
- uses: actions/setup-go@v2
+ uses: actions/setup-go@v4
with:
- go-version: 1.18.x
+ go-version: 1.20.x
- name: Check out code into the Go module directory
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
+ - name: Install dependency required for linux builds
+ if: matrix.os == 'ubuntu-20.04'
+ run: sudo apt-get update && sudo apt-get install -y libudev-dev
+
+ - name: Add Lowercase Repository Name to Environment
+ run: |
+ echo REPOSITORY_NAME_LOWERCASE=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
+
+ - uses: "docker/login-action@v2"
+ if: matrix.os == 'ubuntu-20.04'
+ with:
+ registry: "ghcr.io"
+ username: "${{ github.actor }}"
+ password: "${{ secrets.GITHUB_TOKEN }}"
- name: GoReleaser
- uses: goreleaser/goreleaser-action@v2
+ uses: goreleaser/goreleaser-action@v4
with:
version: latest
- args: release --rm-dist
+ args: release --clean --config .goreleaser.${{ matrix.os }}.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ IMAGE_NAME: ${{ env.REPOSITORY_NAME_LOWERCASE }}
+
+ windows-msi:
+ name: Build Windows MSI and upload to release
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ needs: [release]
+ if: >- # https://github.com/actions/runner/issues/491
+ always() &&
+ (needs.release.result == 'success' || needs.release.result == 'skipped')
+ env:
+ INSTALLER: ${{ github.workspace }}/.github/win-msi
+ BIN: ${{ github.workspace }}/.github/win-msi/src/bin
+ WIXIMG: dactiv/wix@sha256:17d232708589641f5632f9a1ff9463ad087b192cea7b8e6012d2b47ec6af5f6c
+ steps:
+ - name: Normalize tag values
+ run: |
+ if [[ "${{ github.event_name }}" == "workflow_dispatch" ]] ; then
+ VER=${{ github.event.inputs.tag }}
+ else
+ VER=${GITHUB_REF/refs\/tags\//}
+ fi
+
+ VERSION=${VER//v}
+
+ echo "VER_TAG=$VER" >> $GITHUB_ENV
+ echo "VERSION=$VERSION" >> $GITHUB_ENV
+ echo "ASSET=saml2aws_${VERSION}_windows_amd64.zip" >> $GITHUB_ENV
+
+ - name: Check out code
+ uses: actions/checkout@v3
+
+ - name: Retrieve the release asset
+ id: asset
+ uses: robinraju/release-downloader@efa4cd07bd0195e6cc65e9e30c251b49ce4d3e51 # v1.8
+ with:
+ repository: ${{ github.repository }}
+ tag: ${{ env.VER_TAG }}
+ fileName: ${{ env.ASSET }}
+ out-file-path: ${{ env.BIN }}
+
+ - name: Unzip asset
+ working-directory: ${{ env.BIN }}
+ run: unzip "${ASSET}"
+
+ - name: Build MSI
+ run: |
+ # container does not run as root
+ chmod -R o+rw "${INSTALLER}"
+
+ cat "${INSTALLER}/wix.sh" | docker run --rm -i -e VERSION -v "${INSTALLER}:/wix" ${WIXIMG} /bin/sh
+
+ - name: Upload the asset to the release
+ uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15 / v1
+ with:
+ tag_name: ${{ env.VER_TAG }}
+ files: ${{ env.INSTALLER }}/out/*.msi
diff --git a/.gitignore b/.gitignore
index 186524f9f..dab5a8422 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@ vendor
/package
/stage
coverage.txt
+coverage.xml
.ctags
.vscode
bin/
@@ -19,3 +20,4 @@ bin/
# direnv
.envrc
+.buildtemp
\ No newline at end of file
diff --git a/.golangci.yaml b/.golangci.yaml
index 8cd3c6a64..2d5a1d26d 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -2,13 +2,10 @@ linters:
disable-all: true
enable:
- goimports
- - deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- - structcheck
- typecheck
- unused
- - varcheck
diff --git a/.goreleaser.yml b/.goreleaser.macos-latest.yml
similarity index 82%
rename from .goreleaser.yml
rename to .goreleaser.macos-latest.yml
index 393f7c395..de65cbc4a 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.macos-latest.yml
@@ -10,9 +10,7 @@ builds:
ldflags:
- -s -w -X main.Version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
goos:
- - windows
- darwin
- - linux
goarch:
- amd64
- arm64
@@ -20,10 +18,9 @@ builds:
archives:
- format: tar.gz
wrap_in_directory: false
- format_overrides:
- - goos: windows
- format: zip
# remove README and LICENSE
files:
- LICENSE.md
- README.md
+checksum:
+ name_template: "{{ .ProjectName }}_{{ .Version }}_darwin_checksums.txt"
diff --git a/.goreleaser.ubuntu-20.04.yml b/.goreleaser.ubuntu-20.04.yml
new file mode 100644
index 000000000..497fe4787
--- /dev/null
+++ b/.goreleaser.ubuntu-20.04.yml
@@ -0,0 +1,94 @@
+---
+project_name: saml2aws-u2f
+
+builds:
+- id: saml2aws
+ main: ./cmd/saml2aws/main.go
+ binary: saml2aws
+ flags:
+ - -trimpath
+ - -v
+ ldflags:
+ - -s -w -X main.Version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
+ goos:
+ - linux
+ goarch:
+ - amd64
+ overrides:
+ - goos: linux
+ goarch: amd64
+ goamd64: v1
+ tags:
+ - hidraw
+ env:
+ - CGO_ENABLED=1
+- id: saml2aws-static
+ main: ./cmd/saml2aws/main.go
+ binary: saml2aws
+ flags:
+ - -trimpath
+ - -v
+ ldflags:
+ - -s -w -X main.Version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -extldflags "-static"
+ goos:
+ - linux
+ goarch:
+ - amd64
+ - arm64
+ - arm
+ env:
+ - CGO_ENABLED=0
+archives:
+ - id: saml2aws
+ format: tar.gz
+ builds: [saml2aws]
+ wrap_in_directory: false
+ # remove README and LICENSE
+ files:
+ - LICENSE.md
+ - README.md
+ - id: saml2aws-static
+ format: tar.gz
+ builds: [saml2aws-static]
+ wrap_in_directory: false
+ # remove README and LICENSE
+ files:
+ - LICENSE.md
+ - README.md
+ name_template: "{{ .ProjectName }}_static_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
+checksum:
+ name_template: "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
+dockers:
+ - id: amd64
+ goos: linux
+ goarch: amd64
+ use: buildx
+ ids:
+ - saml2aws-static
+ image_templates:
+ - ghcr.io/{{ .Env.IMAGE_NAME }}:{{ .Version }}-amd64
+ - ghcr.io/{{ .Env.IMAGE_NAME }}:latest-amd64
+ build_flag_templates:
+ - "--build-arg=BASE_IMAGE_ARCH=static-debian11"
+ - "--platform=linux/amd64"
+ - id: arm64
+ goos: linux
+ goarch: arm64
+ use: buildx
+ ids:
+ - saml2aws-static
+ image_templates:
+ - ghcr.io/{{ .Env.IMAGE_NAME }}:{{ .Version }}-arm64
+ - ghcr.io/{{ .Env.IMAGE_NAME }}:latest-arm64
+ build_flag_templates:
+ - "--build-arg=BASE_IMAGE_ARCH=static:latest-arm64"
+ - "--platform=linux/arm64"
+docker_manifests:
+ - name_template: ghcr.io/{{ .Env.IMAGE_NAME }}:{{ .Version }}
+ image_templates:
+ - ghcr.io/{{ .Env.IMAGE_NAME }}:{{ .Version }}-amd64
+ - ghcr.io/{{ .Env.IMAGE_NAME }}:{{ .Version }}-arm64
+ - name_template: ghcr.io/{{ .Env.IMAGE_NAME }}:latest
+ image_templates:
+ - ghcr.io/{{ .Env.IMAGE_NAME }}:latest-amd64
+ - ghcr.io/{{ .Env.IMAGE_NAME }}:latest-arm64
\ No newline at end of file
diff --git a/.goreleaser.ubuntu-latest.yml b/.goreleaser.ubuntu-latest.yml
new file mode 100644
index 000000000..5db45000c
--- /dev/null
+++ b/.goreleaser.ubuntu-latest.yml
@@ -0,0 +1,36 @@
+---
+project_name: saml2aws
+
+builds:
+- main: ./cmd/saml2aws/main.go
+ binary: saml2aws
+ flags:
+ - -trimpath
+ - -v
+ ldflags:
+ - -s -w -X main.Version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
+ goos:
+ - windows
+ - linux
+ goarch:
+ - amd64
+ - arm64
+ - arm
+ overrides:
+ - goos: linux
+ goarch: amd64
+ goamd64: v1
+ env:
+ - CGO_ENABLED=0
+archives:
+ - format: tar.gz
+ wrap_in_directory: false
+ format_overrides:
+ - goos: windows
+ format: zip
+ # remove README and LICENSE
+ files:
+ - LICENSE.md
+ - README.md
+checksum:
+ name_template: "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..5a030a50e
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,4 @@
+ARG BASE_IMAGE_ARCH=static-debian11
+FROM gcr.io/distroless/$BASE_IMAGE_ARCH
+COPY saml2aws /
+ENTRYPOINT ["/saml2aws"]
\ No newline at end of file
diff --git a/Dockerfile.build b/Dockerfile.build
new file mode 100644
index 000000000..5d70bc62f
--- /dev/null
+++ b/Dockerfile.build
@@ -0,0 +1,37 @@
+# base image
+FROM ubuntu:jammy
+ENV TZ=Australia/Sydney
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+# add arm64 architecture
+RUN apt-get update
+RUN dpkg --add-architecture arm64
+
+## arch-qualify the current repositories
+RUN sed -i "s/deb h/deb [arch=amd64] h/g" /etc/apt/sources.list
+
+## add arm64's repos
+RUN echo "# arm64 repositories" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy universe" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates universe" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security universe" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security multiverse" >> /etc/apt/sources.list
+
+RUN apt-get update && apt-get install -y build-essential git ca-certificates golang libudev-dev curl gnupg lsb-release curl gcc-arm* binutils-arm-linux-gnueabi crossbuild-essential-arm64 wget
+
+RUN echo \
+ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
+ $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
+RUN apt-get update && apt-get install -y docker-ce-cli
+# Replicate install of the same version of Golang that we are using in Github actions
+RUN wget https://go.dev/dl/go1.20.2.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.20.2.linux-amd64.tar.gz && rm go1.20.2.linux-amd64.tar.gz
+RUN go install github.com/goreleaser/goreleaser@latest
+ENV GOROOT="/usr/local/go"
+ENV PATH="/root/go/bin:$GOROOT/bin:${PATH}"
diff --git a/Makefile b/Makefile
index 3dac85ed8..1db3490e5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
NAME=saml2aws
ARCH=$(shell uname -m)
-VERSION=2.28.0
+OS?=$(shell uname)
ITERATION := 1
GOLANGCI_VERSION = 1.45.2
-GORELEASER_VERSION = 0.157.0
+GORELEASER := $(shell command -v goreleaser 2> /dev/null)
SOURCE_FILES?=$$(go list ./... | grep -v /vendor/)
TEST_PATTERN?=.
@@ -12,6 +12,15 @@ TEST_OPTIONS?=
BIN_DIR := $(CURDIR)/bin
+# Choose the right config file for the OS
+ifeq ($(OS),Darwin)
+ CONFIG_FILE?=$(CURDIR)/.goreleaser.macos-latest.yml
+else ifeq ($(OS),Linux)
+ CONFIG_FILE?=$(CURDIR)/.goreleaser.ubuntu-20.04.yml
+else
+ $(error Unsupported build OS: $(OS))
+endif
+
ci: prepare test
mod:
@@ -35,10 +44,18 @@ install:
go install ./cmd/saml2aws
.PHONY: mod
-build: $(BIN_DIR)/goreleaser
- $(BIN_DIR)/goreleaser build --snapshot --rm-dist
+build:
+
+ifndef GORELEASER
+ $(error "goreleaser is not available please install and ensure it is on PATH")
+endif
+ goreleaser build --snapshot --clean --config $(CONFIG_FILE)
.PHONY: build
+release-local: $(BIN_DIR)/goreleaser
+ goreleaser release --snapshot --rm-dist --config $(CONFIG_FILE)
+.PHONY: release-local
+
clean:
@rm -fr ./build
.PHONY: clean
@@ -52,3 +69,15 @@ test:
@echo "--- test all the things"
@go test -cover ./...
.PHONY: test
+
+# It can be difficult to set up and test everything locally. Using this target you can build and run a docker container
+# that has all the tools you need to build and test saml2aws. This is particularly useful on Mac as it allows the Linux
+# and Docker builds to be tested.
+# Note: By necessity, this target mounts the Docker socket into the container. This is a security risk and should not
+# be used on a production system.
+# Note: Files written by the container will be owned by root. This is a limitation of the Docker socket mount.
+# You may need to run `docker run --privileged --rm tonistiigi/binfmt --install all` to enable the buildx plugin.
+docker-build-environment:
+ docker build --platform=amd64 -t saml2aws/build -f Dockerfile.build .
+ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock -e BUILDX_CONFIG=$(PWD)/.buildtemp -e GOPATH=$(PWD)/.buildtemp -e GOTMPDIR=$(PWD)/.buildtemp -e GOCACHE=$(PWD)/.buildtemp/.cache -e GOENV=$(PWD)/.buildtemp/env -v $(PWD):$(PWD) -w $(PWD) saml2aws/build:latest
+.PHONY: docker-build-environment
\ No newline at end of file
diff --git a/README.md b/README.md
index db2717cb6..2888cfd45 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
-# saml2aws [![GitHub Actions status](https://github.com/Versent/saml2aws/workflows/Go/badge.svg?branch=master)](https://github.com/Versent/saml2aws/actions?query=workflow%3AGo) [![Build status - Windows](https://ci.appveyor.com/api/projects/status/ptpi18kci16o4i82/branch/master?svg=true)](https://ci.appveyor.com/project/davidobrien1985/saml2aws/branch/master)
+# saml2aws
+
+[![GitHub Actions status](https://github.com/Versent/saml2aws/workflows/Go/badge.svg?branch=master)](https://github.com/Versent/saml2aws/actions?query=workflow%3AGo) [![Build status - Windows](https://ci.appveyor.com/api/projects/status/ptpi18kci16o4i82/branch/master?svg=true)](https://ci.appveyor.com/project/davidobrien1985/saml2aws/branch/master)
+[![codecov](https://codecov.io/gh/Versent/saml2aws/branch/master/graph/badge.svg)](https://codecov.io/gh/Versent/saml2aws)
CLI tool which enables you to login and retrieve [AWS](https://aws.amazon.com/) temporary credentials using
with [ADFS](https://msdn.microsoft.com/en-us/library/bb897402.aspx) or [PingFederate](https://www.pingidentity.com/en/products/pingfederate.html) Identity Providers.
@@ -18,25 +21,47 @@ The process goes something like this:
## Table of Contents
-- [Table of Contents](#table-of-contents)
-- [Requirements](#requirements)
-- [Caveats](#caveats)
-- [Install](#install)
+- [saml2aws](#saml2aws)
+ - [Table of Contents](#table-of-contents)
+ - [Requirements](#requirements)
+ - [Caveats](#caveats)
+ - [Install](#install)
- [OSX](#osx)
- [Windows](#windows)
- [Linux](#linux)
-- [Autocomplete](#autocomplete)
-- [Dependency Setup](#dependency-setup)
-- [Usage](#usage)
+ - [Using Make](#using-make)
+ - [Arch Linux and its derivatives](#arch-linux-and-its-derivatives)
+ - [Void Linux](#void-linux)
+ - [Autocomplete](#autocomplete)
+ - [Bash](#bash)
+ - [Zsh](#zsh)
+ - [Dependency Setup](#dependency-setup)
+ - [Usage](#usage)
- [`saml2aws script`](#saml2aws-script)
+ - [`saml2aws exec`](#saml2aws-exec)
- [Configuring IDP Accounts](#configuring-idp-accounts)
-- [Example](#example)
-- [Advanced Configuration](#advanced-configuration)
- - [Dev Account Setup](#dev-account-setup)
- - [Test Account Setup](#test-account-setup)
-- [Building](#building)
-- [Environment vars](#environment-vars)
-- [Provider Specific Documentation](#provider-specific-documentation)
+ - [Example](#example)
+ - [Advanced Configuration](#advanced-configuration)
+ - [Windows Subsystem Linux (WSL) Configuration](#windows-subsystem-linux-wsl-configuration)
+ - [Option 1: Disable Keychain](#option-1-disable-keychain)
+ - [Option 2: Configure Pass to be the default keyring](#option-2-configure-pass-to-be-the-default-keyring)
+ - [Configuring Multiple Accounts](#configuring-multiple-accounts)
+ - [Dev Account Setup](#dev-account-setup)
+ - [Test Account Setup](#test-account-setup)
+ - [Advanced Configuration (Multiple AWS account access but SAML authenticate against a single 'SSO' AWS account)](#advanced-configuration-multiple-aws-account-access-but-saml-authenticate-against-a-single-sso-aws-account)
+ - [Advanced Configuration - additional parameters](#advanced-configuration---additional-parameters)
+ - [Building](#building)
+ - [macOS](#macos)
+ - [Linux](#linux-1)
+ - [Environment vars](#environment-vars)
+ - [Provider Specific Documentation](#provider-specific-documentation)
+- [Dependencies](#dependencies)
+- [Releasing](#releasing)
+- [Debugging Issues with IDPs](#debugging-issues-with-idps)
+- [Using saml2aws as credential process](#using-saml2aws-as-credential-process)
+- [Caching the saml2aws SAML assertion for immediate reuse](#caching-the-saml2aws-saml-assertion-for-immediate-reuse)
+- [Okta Sessions](#okta-sessions)
+- [License](#license)
## Requirements
@@ -52,7 +77,7 @@ The process goes something like this:
* [Akamai](pkg/provider/akamai/README.md)
* OneLogin
* NetIQ
- * Browser, this uses [playwright-go](github.com/mxschmitt/playwright-go) to run a sandbox chromium window.
+ * Browser, this uses [playwright-go](github.com/playwright-community/playwright-go) to run a sandbox chromium window.
* [Auth0](pkg/provider/auth0/README.md) NOTE: Currently, MFA not supported
* AWS SAML Provider configured
@@ -89,12 +114,30 @@ saml2aws --version
While brew is available for Linux you can also run the following without using a package manager.
```
+mkdir -p ~/.local/bin
CURRENT_VERSION=$(curl -Ls https://api.github.com/repos/Versent/saml2aws/releases/latest | grep 'tag_name' | cut -d'v' -f2 | cut -d'"' -f1)
-wget -c https://github.com/Versent/saml2aws/releases/download/v${CURRENT_VERSION}/saml2aws_${CURRENT_VERSION}_linux_amd64.tar.gz -O - | tar -xzv -C ~/.local/bin
+wget -c "https://github.com/Versent/saml2aws/releases/download/v${CURRENT_VERSION}/saml2aws_${CURRENT_VERSION}_linux_amd64.tar.gz" -O - | tar -xzv -C ~/.local/bin
chmod u+x ~/.local/bin/saml2aws
hash -r
saml2aws --version
```
+If U2F support is required then there are separate builds for this - use the following download URL instead:
+```
+wget -c "https://github.com/Versent/saml2aws/releases/download/v${CURRENT_VERSION}/saml2aws-u2f_${CURRENT_VERSION}_linux_amd64.tar.gz" -O - | tar -xzv -C ~/.local/bin
+```
+
+#### Using Make
+
+You will need [Go Tools](https://golang.org/doc/install) (you can check your package maintainer as well) installed and the [Go Lint tool](https://github.com/alecthomas/gometalinter)
+
+Clone this repo to your `$GOPATH/src` directory
+
+Now you can install by running
+
+```
+make
+make install
+```
#### [Arch Linux](https://archlinux.org/) and its derivatives
@@ -179,6 +222,8 @@ Commands:
--client-secret=CLIENT-SECRET
OneLogin client secret, used to generate API access token. (env: ONELOGIN_CLIENT_SECRET)
--subdomain=SUBDOMAIN OneLogin subdomain of your company account. (env: ONELOGIN_SUBDOMAIN)
+ --mfa-ip-address=MFA-IP-ADDRESS
+ IP address whitelisting defined in OneLogin MFA policies. (env: ONELOGIN_MFA_IP_ADDRESS)
-p, --profile=PROFILE The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)
--resource-id=RESOURCE-ID F5APM SAML resource ID of your company account. (env: SAML2AWS_F5APM_RESOURCE_ID)
--config=CONFIG Path/filename of saml2aws config file (env: SAML2AWS_CONFIGFILE)
@@ -196,12 +241,15 @@ Commands:
--client-id=CLIENT-ID OneLogin client id, used to generate API access token. (env: ONELOGIN_CLIENT_ID)
--client-secret=CLIENT-SECRET
OneLogin client secret, used to generate API access token. (env: ONELOGIN_CLIENT_SECRET)
+ --mfa-ip-address=MFA-IP-ADDRESS
+ IP address whitelisting defined in OneLogin MFA policies. (env: ONELOGIN_MFA_IP_ADDRESS)
--force Refresh credentials even if not expired.
--credential-process Enables AWS Credential Process support by outputting credentials to STDOUT in a JSON message.
--credentials-file=CREDENTIALS-FILE
The file that will cache the credentials retrieved from AWS. When not specified, will use the default AWS credentials file location. (env: SAML2AWS_CREDENTIALS_FILE)
--cache-saml Caches the SAML response (env: SAML2AWS_CACHE_SAML)
--cache-file=CACHE-FILE The location of the SAML cache file (env: SAML2AWS_SAML_CACHE_FILE)
+ --download-browser-driver Automatically download browsers for Browser IDP. (env: SAML2AWS_AUTO_BROWSER_DOWNLOAD)
--disable-sessions Do not use Okta sessions. Uses Okta sessions by default. (env: SAML2AWS_OKTA_DISABLE_SESSIONS)
--disable-remember-device Do not remember Okta MFA device. Remembers MFA device by default. (env: SAML2AWS_OKTA_DISABLE_REMEMBER_DEVICE)
@@ -235,7 +283,7 @@ Commands:
Emit a script that will export environment variables.
-p, --profile=PROFILE The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)
- --shell=bash Type of shell environment. Options include: bash, powershell, fish, env
+ --shell=bash Type of shell environment. Options include: bash, /bin/sh, powershell, fish, env
--credentials-file=CREDENTIALS-FILE
The file that will cache the credentials retrieved from AWS. When not specified, will use the default AWS credentials file location. (env: SAML2AWS_CREDENTIALS_FILE)
@@ -255,7 +303,7 @@ export AWS_CREDENTIAL_EXPIRATION="2016-09-04T38:27:00Z00:00"
SAML2AWS_PROFILE=saml
```
-Powershell, and fish shells are supported as well.
+Powershell, sh and fish shells are supported as well.
Env is useful for all AWS SDK compatible tools that can source an env file. It is a powerful combo with docker and the `--env-file` parameter.
If you use `eval $(saml2aws script)` frequently, you may want to create a alias for it:
@@ -498,6 +546,18 @@ region = us-east-1
To use this you will need to export `AWS_DEFAULT_PROFILE=customer-test` environment variable to target `test`.
+### Playwright Browser Drivers for Browser IDP
+
+If you are using the Browser Identity Provider, on first invocation of `saml2aws login` you need to remember to install
+the browser drivers in order for playwright-go to work. Otherwise you will see the following error message:
+
+`Error authenticating to IDP.: could not start driver: fork/exec ... no such file or directory`
+
+To install the drivers, you can:
+* Pass `--download-browser-driver` to `saml2aws login`
+* Set in your shell environment `SAML2AWS_AUTO_BROWSER_DOWNLOAD=true`
+* Set `download_browser_driver = true` in your saml2aws config file, i.e. `~/.saml2aws`
+
## Advanced Configuration (Multiple AWS account access but SAML authenticate against a single 'SSO' AWS account)
Example:
@@ -629,6 +689,8 @@ region = us-east-1
```
## Building
+### macOS
+
To build this software on osx clone to the repo to `$GOPATH/src/github.com/versent/saml2aws` and ensure you have `$GOPATH/bin` in your `$PATH`.
```
@@ -653,6 +715,26 @@ Before raising a PR please run the linter.
make lint-fix
```
+### Linux
+
+To build this software on Debian/Ubuntu, you need to install a build dependency:
+
+```
+sudo apt install libudev-dev
+```
+
+You also need [GoReleaser](https://github.com/goreleaser/goreleaser) installed, and the binary (or a symlink) in `bin/goreleaser`.
+
+```
+ln -s $(command -v goreleaser) bin/goreleaser
+```
+
+Then you can build:
+
+```
+make build
+```
+
## Environment vars
The exec sub command will export the following environment variables.
diff --git a/aws_account.go b/aws_account.go
index bdf7e83d6..ff28c3abf 100644
--- a/aws_account.go
+++ b/aws_account.go
@@ -3,7 +3,7 @@ package saml2aws
import (
"bytes"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
@@ -24,7 +24,7 @@ func ParseAWSAccounts(audience string, samlAssertion string) ([]*AWSAccount, err
return nil, errors.Wrap(err, "error retrieving AWS login form")
}
- data, err := ioutil.ReadAll(res.Body)
+ data, err := io.ReadAll(res.Body)
if err != nil {
return nil, errors.Wrap(err, "error retrieving AWS login body")
}
diff --git a/aws_account_test.go b/aws_account_test.go
index 9ea4ec11c..b5c86c43b 100644
--- a/aws_account_test.go
+++ b/aws_account_test.go
@@ -1,14 +1,14 @@
package saml2aws
import (
- "io/ioutil"
+ "os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestExtractAWSAccounts(t *testing.T) {
- data, err := ioutil.ReadFile("testdata/saml.html")
+ data, err := os.ReadFile("testdata/saml.html")
assert.Nil(t, err)
accounts, err := ExtractAWSAccounts(data)
diff --git a/aws_role.go b/aws_role.go
index c843f9b8f..60ff2246b 100644
--- a/aws_role.go
+++ b/aws_role.go
@@ -2,6 +2,7 @@ package saml2aws
import (
"fmt"
+ "regexp"
"strings"
)
@@ -29,7 +30,8 @@ func ParseAWSRoles(roles []string) ([]*AWSRole, error) {
}
func parseRole(role string) (*AWSRole, error) {
- tokens := strings.Split(role, ",")
+ r, _ := regexp.Compile("arn:([^:\n]*):([^:\n]*):([^:\n]*):([^:\n]*):(([^:/\n]*)[:/])?([^:,\n]*)")
+ tokens := r.FindAllString(role, -1)
if len(tokens) != 2 {
return nil, fmt.Errorf("Invalid role string only %d tokens", len(tokens))
diff --git a/choco/VERIFICATION.txt b/choco/VERIFICATION.txt
index 02109c0a6..0b4e283e8 100644
--- a/choco/VERIFICATION.txt
+++ b/choco/VERIFICATION.txt
@@ -2,7 +2,7 @@ VERIFICATION
Verification is intended to assist the Chocolatey moderators and community
in verifying that this package's contents are trustworthy.
-The installer has been automatically built from source whch can be found on
+The installer has been automatically built from source which can be found on
and can be verified like this:
1. Download the release version from
@@ -11,4 +11,4 @@ and can be verified like this:
- Use chocolatey utility 'checksum.exe'
Compare the checksums there with the checksum of the local binary in C:\ProgramData\Chocolatey\lib\saml2aws\src\saml2aws.exe
-File 'LICENSE.txt' is obtained from .
\ No newline at end of file
+File 'LICENSE.txt' is obtained from .
diff --git a/cmd/saml2aws/commands/console.go b/cmd/saml2aws/commands/console.go
index cf11bf0d3..70e1f20d6 100644
--- a/cmd/saml2aws/commands/console.go
+++ b/cmd/saml2aws/commands/console.go
@@ -3,7 +3,7 @@ package commands
import (
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"log"
"net/http"
"net/url"
@@ -136,7 +136,7 @@ func federatedLogin(creds *awsconfig.AWSCredentials, consoleFlags *flags.Console
}
defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
+ body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
diff --git a/cmd/saml2aws/commands/login.go b/cmd/saml2aws/commands/login.go
index 86fe3ffd0..0a7766a4e 100644
--- a/cmd/saml2aws/commands/login.go
+++ b/cmd/saml2aws/commands/login.go
@@ -217,6 +217,19 @@ func resolveLoginDetails(account *cfg.IDPAccount, loginFlags *flags.LoginExecFla
loginDetails.ClientSecret = loginFlags.CommonFlags.ClientSecret
}
+ // if you supply an mfa_ip_address in a flag or an IDP account it takes precedence
+ if account.MFAIPAddress != "" {
+ loginDetails.MFAIPAddress = account.MFAIPAddress
+ } else if loginFlags.CommonFlags.MFAIPAddress != "" {
+ loginDetails.MFAIPAddress = loginFlags.CommonFlags.MFAIPAddress
+ }
+
+ if loginFlags.DownloadBrowser {
+ loginDetails.DownloadBrowser = loginFlags.DownloadBrowser
+ } else if account.DownloadBrowser {
+ loginDetails.DownloadBrowser = account.DownloadBrowser
+ }
+
// log.Printf("loginDetails %+v", loginDetails)
// if skip prompt was passed just pass back the flag values
diff --git a/cmd/saml2aws/commands/login_darwin.go b/cmd/saml2aws/commands/login_darwin.go
index 14b4d9bbe..c2d036354 100644
--- a/cmd/saml2aws/commands/login_darwin.go
+++ b/cmd/saml2aws/commands/login_darwin.go
@@ -1,3 +1,4 @@
+//go:build darwin && cgo
// +build darwin,cgo
package commands
diff --git a/cmd/saml2aws/commands/login_test.go b/cmd/saml2aws/commands/login_test.go
index 0e29f3640..bca0442cf 100644
--- a/cmd/saml2aws/commands/login_test.go
+++ b/cmd/saml2aws/commands/login_test.go
@@ -15,7 +15,7 @@ import (
func TestResolveLoginDetailsWithFlags(t *testing.T) {
- commonFlags := &flags.CommonFlags{URL: "https://id.example.com", Username: "wolfeidau", Password: "testtestlol", MFAToken: "123456", SkipPrompt: true}
+ commonFlags := &flags.CommonFlags{URL: "https://id.example.com", Username: "wolfeidau", Password: "testtestlol", MFAIPAddress: "127.0.0.1", MFAToken: "123456", SkipPrompt: true}
loginFlags := &flags.LoginExecFlags{CommonFlags: commonFlags}
idpa := &cfg.IDPAccount{
@@ -27,7 +27,7 @@ func TestResolveLoginDetailsWithFlags(t *testing.T) {
loginDetails, err := resolveLoginDetails(idpa, loginFlags)
assert.Empty(t, err)
- assert.Equal(t, &creds.LoginDetails{Username: "wolfeidau", Password: "testtestlol", URL: "https://id.example.com", MFAToken: "123456"}, loginDetails)
+ assert.Equal(t, &creds.LoginDetails{Username: "wolfeidau", Password: "testtestlol", URL: "https://id.example.com", MFAToken: "123456", MFAIPAddress: "127.0.0.1"}, loginDetails)
}
func TestOktaResolveLoginDetailsWithFlags(t *testing.T) {
diff --git a/cmd/saml2aws/commands/script.go b/cmd/saml2aws/commands/script.go
index 4a736e6b4..0f35b3dbd 100644
--- a/cmd/saml2aws/commands/script.go
+++ b/cmd/saml2aws/commands/script.go
@@ -20,6 +20,14 @@ export SAML2AWS_PROFILE={{ .ProfileName }}
export AWS_CREDENTIAL_EXPIRATION={{ .Expires.Format "2006-01-02T15:04:05Z07:00" }}
`
+const shTmpl = `export AWS_ACCESS_KEY_ID={{ .AWSAccessKey }}
+export AWS_SECRET_ACCESS_KEY={{ .AWSSecretKey }}
+export AWS_SESSION_TOKEN={{ .AWSSessionToken }}
+export AWS_SECURITY_TOKEN={{ .AWSSecurityToken }}
+export SAML2AWS_PROFILE={{ .ProfileName }}
+export AWS_CREDENTIAL_EXPIRATION={{ .Expires.Format "2006-01-02T15:04:05Z07:00" }}
+`
+
const fishTmpl = `set -gx AWS_ACCESS_KEY_ID {{ .AWSAccessKey }}
set -gx AWS_SECRET_ACCESS_KEY {{ .AWSSecretKey }}
set -gx AWS_SESSION_TOKEN {{ .AWSSessionToken }}
@@ -99,6 +107,8 @@ func buildTmpl(shell string, data interface{}) (string, error) {
switch shell {
case "bash":
t, err = t.Parse(bashTmpl)
+ case "/bin/sh":
+ t, err = t.Parse(shTmpl)
case "powershell":
t, err = t.Parse(powershellTmpl)
case "fish":
diff --git a/cmd/saml2aws/commands/script_test.go b/cmd/saml2aws/commands/script_test.go
index 0e44073c4..9d458584f 100644
--- a/cmd/saml2aws/commands/script_test.go
+++ b/cmd/saml2aws/commands/script_test.go
@@ -25,7 +25,40 @@ func TestBuildTmplBash(t *testing.T) {
}
st, err := buildTmpl("bash", data)
- assert.ErrorIs(t, err, nil)
+ assert.Nil(t, err)
+
+ expected := []string{
+ "export AWS_ACCESS_KEY_ID=access_key",
+ "export AWS_SECRET_ACCESS_KEY=secret_key",
+ "export AWS_SESSION_TOKEN=session_token",
+ "export AWS_SECURITY_TOKEN=security_token",
+ "export SAML2AWS_PROFILE=test_profile",
+ }
+
+ for _, test_string := range expected {
+ assert.Contains(t, st, test_string)
+ }
+
+}
+
+func TestBuildTmplSh(t *testing.T) {
+
+ data := struct {
+ ProfileName string
+ *awsconfig.AWSCredentials
+ }{
+ "test_profile",
+ &awsconfig.AWSCredentials{
+ AWSSecretKey: "secret_key",
+ AWSAccessKey: "access_key",
+ AWSSessionToken: "session_token",
+ AWSSecurityToken: "security_token",
+ Expires: time.Now(),
+ },
+ }
+
+ st, err := buildTmpl("/bin/sh", data)
+ assert.Nil(t, err)
expected := []string{
"export AWS_ACCESS_KEY_ID=access_key",
@@ -58,7 +91,7 @@ func TestBuildTmplFish(t *testing.T) {
}
st, err := buildTmpl("fish", data)
- assert.ErrorIs(t, err, nil)
+ assert.Nil(t, err)
expected := []string{
"set -gx AWS_ACCESS_KEY_ID access_key",
@@ -91,7 +124,7 @@ func TestBuildTmplEnv(t *testing.T) {
}
st, err := buildTmpl("env", data)
- assert.ErrorIs(t, err, nil)
+ assert.Nil(t, err)
expected := []string{
"AWS_ACCESS_KEY_ID=access_key",
diff --git a/cmd/saml2aws/main.go b/cmd/saml2aws/main.go
index d6ee181e3..328400df3 100644
--- a/cmd/saml2aws/main.go
+++ b/cmd/saml2aws/main.go
@@ -2,7 +2,7 @@ package main
import (
"crypto/tls"
- "io/ioutil"
+ "io"
"log"
"net/http"
"os"
@@ -90,6 +90,7 @@ func main() {
cmdConfigure.Flag("client-id", "OneLogin client id, used to generate API access token. (env: ONELOGIN_CLIENT_ID)").Envar("ONELOGIN_CLIENT_ID").StringVar(&commonFlags.ClientID)
cmdConfigure.Flag("client-secret", "OneLogin client secret, used to generate API access token. (env: ONELOGIN_CLIENT_SECRET)").Envar("ONELOGIN_CLIENT_SECRET").StringVar(&commonFlags.ClientSecret)
cmdConfigure.Flag("subdomain", "OneLogin subdomain of your company account. (env: ONELOGIN_SUBDOMAIN)").Envar("ONELOGIN_SUBDOMAIN").StringVar(&commonFlags.Subdomain)
+ cmdConfigure.Flag("mfa-ip-address", "IP address whitelisting defined in OneLogin MFA policies. (env: ONELOGIN_MFA_IP_ADDRESS)").Envar("ONELOGIN_MFA_IP_ADDRESS").StringVar(&commonFlags.MFAIPAddress)
cmdConfigure.Flag("profile", "The AWS profile to save the temporary credentials. (env: SAML2AWS_PROFILE)").Envar("SAML2AWS_PROFILE").Short('p').StringVar(&commonFlags.Profile)
cmdConfigure.Flag("resource-id", "F5APM SAML resource ID of your company account. (env: SAML2AWS_F5APM_RESOURCE_ID)").Envar("SAML2AWS_F5APM_RESOURCE_ID").StringVar(&commonFlags.ResourceID)
cmdConfigure.Flag("credentials-file", "The file that will cache the credentials retrieved from AWS. When not specified, will use the default AWS credentials file location. (env: SAML2AWS_CREDENTIALS_FILE)").Envar("SAML2AWS_CREDENTIALS_FILE").StringVar(&commonFlags.CredentialsFile)
@@ -107,11 +108,13 @@ func main() {
cmdLogin.Flag("duo-mfa-option", "The MFA option you want to use to authenticate with").Envar("SAML2AWS_DUO_MFA_OPTION").EnumVar(&loginFlags.DuoMFAOption, "Passcode", "Phone Call", "Duo Push")
cmdLogin.Flag("client-id", "OneLogin client id, used to generate API access token. (env: ONELOGIN_CLIENT_ID)").Envar("ONELOGIN_CLIENT_ID").StringVar(&commonFlags.ClientID)
cmdLogin.Flag("client-secret", "OneLogin client secret, used to generate API access token. (env: ONELOGIN_CLIENT_SECRET)").Envar("ONELOGIN_CLIENT_SECRET").StringVar(&commonFlags.ClientSecret)
+ cmdLogin.Flag("mfa-ip-address", "IP address whitelisting defined in OneLogin MFA policies. (env: ONELOGIN_MFA_IP_ADDRESS)").Envar("ONELOGIN_MFA_IP_ADDRESS").StringVar(&commonFlags.MFAIPAddress)
cmdLogin.Flag("force", "Refresh credentials even if not expired.").BoolVar(&loginFlags.Force)
cmdLogin.Flag("credential-process", "Enables AWS Credential Process support by outputting credentials to STDOUT in a JSON message.").BoolVar(&loginFlags.CredentialProcess)
cmdLogin.Flag("credentials-file", "The file that will cache the credentials retrieved from AWS. When not specified, will use the default AWS credentials file location. (env: SAML2AWS_CREDENTIALS_FILE)").Envar("SAML2AWS_CREDENTIALS_FILE").StringVar(&commonFlags.CredentialsFile)
cmdLogin.Flag("cache-saml", "Caches the SAML response (env: SAML2AWS_CACHE_SAML)").Envar("SAML2AWS_CACHE_SAML").BoolVar(&commonFlags.SAMLCache)
cmdLogin.Flag("cache-file", "The location of the SAML cache file (env: SAML2AWS_SAML_CACHE_FILE)").Envar("SAML2AWS_SAML_CACHE_FILE").StringVar(&commonFlags.SAMLCacheFile)
+ cmdLogin.Flag("download-browser-driver", "Automatically download browsers for Browser IDP. (env: SAML2AWS_AUTO_BROWSER_DOWNLOAD)").Envar("SAML2AWS_AUTO_BROWSER_DOWNLOAD").BoolVar(&loginFlags.DownloadBrowser)
cmdLogin.Flag("disable-sessions", "Do not use Okta sessions. Uses Okta sessions by default. (env: SAML2AWS_OKTA_DISABLE_SESSIONS)").Envar("SAML2AWS_OKTA_DISABLE_SESSIONS").BoolVar(&commonFlags.DisableSessions)
cmdLogin.Flag("disable-remember-device", "Do not remember Okta MFA device. Remembers MFA device by default. (env: SAML2AWS_OKTA_DISABLE_REMEMBER_DEVICE)").Envar("SAML2AWS_OKTA_DISABLE_REMEMBER_DEVICE").BoolVar(&commonFlags.DisableRememberDevice)
@@ -150,9 +153,9 @@ func main() {
cmdScript.Flag("credentials-file", "The file that will cache the credentials retrieved from AWS. When not specified, will use the default AWS credentials file location. (env: SAML2AWS_CREDENTIALS_FILE)").Envar("SAML2AWS_CREDENTIALS_FILE").StringVar(&commonFlags.CredentialsFile)
var shell string
cmdScript.
- Flag("shell", "Type of shell environment. Options include: bash, powershell, fish, env").
+ Flag("shell", "Type of shell environment. Options include: bash, /bin/sh, powershell, fish, env").
Default("bash").
- EnumVar(&shell, "bash", "powershell", "fish", "env")
+ EnumVar(&shell, "bash", "/bin/sh", "powershell", "fish", "env")
// Trigger the parsing of the command line inputs via kingpin
command := kingpin.MustParse(app.Parse(os.Args[1:]))
@@ -170,8 +173,8 @@ func main() {
}
if *quiet {
- log.SetOutput(ioutil.Discard)
- logrus.SetOutput(ioutil.Discard)
+ log.SetOutput(io.Discard)
+ logrus.SetOutput(io.Discard)
}
// Set the default transport settings so all http clients will pick them up.
diff --git a/coverage.xml b/coverage.xml
deleted file mode 100644
index 3f52527f0..000000000
--- a/coverage.xml
+++ /dev/null
@@ -1,11135 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/go.mod b/go.mod
index 82f225175..ccbfe7b86 100644
--- a/go.mod
+++ b/go.mod
@@ -1,29 +1,30 @@
module github.com/versent/saml2aws/v2
-go 1.18
+go 1.20
require (
- github.com/99designs/keyring v1.2.1
- github.com/AlecAivazis/survey/v2 v2.3.5
+ github.com/99designs/keyring v1.2.2
+ github.com/AlecAivazis/survey/v2 v2.3.6
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e
- github.com/PuerkitoBio/goquery v1.8.0
+ github.com/PuerkitoBio/goquery v1.8.1
github.com/alecthomas/kingpin v2.2.6+incompatible
github.com/avast/retry-go v3.0.0+incompatible
- github.com/aws/aws-sdk-go v1.44.59
- github.com/beevik/etree v1.1.0
- github.com/danieljoos/wincred v1.1.2
+ github.com/aws/aws-sdk-go v1.44.281
+ github.com/beevik/etree v1.2.0
+ github.com/danieljoos/wincred v1.2.0
github.com/google/uuid v1.3.0
+ github.com/h2non/gock v1.2.0
github.com/keybase/go-keychain v0.0.0-20211119201326-e02f34051621
github.com/marshallbrekka/go-u2fhost v0.0.0-20210111072507-3ccdec8c8105
github.com/mitchellh/go-homedir v1.1.0
- github.com/mxschmitt/playwright-go v0.1400.0
github.com/pkg/errors v0.9.1
- github.com/sirupsen/logrus v1.9.0
+ github.com/playwright-community/playwright-go v0.2000.1
+ github.com/sirupsen/logrus v1.9.3
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
- github.com/stretchr/testify v1.8.0
- github.com/tidwall/gjson v1.14.1
- golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
- gopkg.in/ini.v1 v1.66.6
+ github.com/stretchr/testify v1.8.4
+ github.com/tidwall/gjson v1.14.4
+ golang.org/x/net v0.10.0
+ gopkg.in/ini.v1 v1.67.0
)
require (
@@ -35,9 +36,10 @@ require (
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
+ github.com/go-stack/stack v1.8.1 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
- github.com/gorilla/websocket v1.4.2 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
+ github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
@@ -45,13 +47,13 @@ require (
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/stretchr/objx v0.4.0 // indirect
+ github.com/stretchr/objx v0.5.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
- golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 // indirect
- golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
- golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
- golang.org/x/text v0.3.7 // indirect
+ golang.org/x/crypto v0.1.0 // indirect
+ golang.org/x/sys v0.8.0 // indirect
+ golang.org/x/term v0.8.0 // indirect
+ golang.org/x/text v0.9.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index ee8ddca7b..cbee5c5ec 100644
--- a/go.sum
+++ b/go.sum
@@ -1,18 +1,18 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4=
-github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o=
-github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA=
-github.com/AlecAivazis/survey/v2 v2.3.5 h1:A8cYupsAZkjaUmhtTYv3sSqc7LO5mp1XDfqe5E/9wRQ=
-github.com/AlecAivazis/survey/v2 v2.3.5/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
+github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0=
+github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk=
+github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw=
+github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e h1:ZU22z/2YRFLyf/P4ZwUYSdNCWsMEI0VeyrFoI2rAhJQ=
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
-github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
+github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
+github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI=
github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
@@ -24,12 +24,12 @@ github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEq
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
-github.com/aws/aws-sdk-go v1.44.59 h1:bkdnNsMvMhFmNLqKDAJ6rKR+S0hjOt/3AIJp2mxOK9o=
-github.com/aws/aws-sdk-go v1.44.59/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
+github.com/aws/aws-sdk-go v1.44.281 h1:z/ptheJvINaIAsKXthxONM+toTKw2pxyk700Hfm6yUw=
+github.com/aws/aws-sdk-go v1.44.281/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/bearsh/hid v1.3.0 h1:GLNa8hvEzJxzQEEpheDUr2SivvH7iwTrJrDhFKutfX8=
github.com/bearsh/hid v1.3.0/go.mod h1:KbQByg8WfPr92v7aaKAHTtZUEVG7e2XRpcF8+TopQv8=
-github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
-github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
+github.com/beevik/etree v1.2.0 h1:l7WETslUG/T+xOPs47dtd6jov2Ii/8/OjCldk5fYfQw=
+github.com/beevik/etree v1.2.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -42,8 +42,8 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
-github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
-github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
+github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE=
+github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -59,6 +59,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
+github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -73,7 +75,6 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
@@ -81,6 +82,10 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
+github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
+github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
+github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
+github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
@@ -120,8 +125,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mxschmitt/playwright-go v0.1400.0 h1:HL8dbxcVEobE+pNjASeYGJJRmd4+9gyu/51XO7d3qF0=
-github.com/mxschmitt/playwright-go v0.1400.0/go.mod h1:kUvZFgMneRGknVLtC2DKQ42lhZiCmWzxgBdGwjC0vkw=
+github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
+github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
@@ -129,6 +134,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/playwright-community/playwright-go v0.2000.1 h1:2JViSHpJQ/UL/PO1Gg6gXV5IcXAAsoBJ3KG9L3wKXto=
+github.com/playwright-community/playwright-go v0.2000.1/go.mod h1:1y9cM9b9dVHnuRWzED1KLM7FtbwTJC8ibDjI6MNqewU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -145,8 +152,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
-github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
-github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -159,16 +166,18 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
-github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
+github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
@@ -177,59 +186,79 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
-golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
+golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -239,8 +268,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
-gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
diff --git a/helper/osxkeychain/keychain.go b/helper/osxkeychain/keychain.go
index 3a9ec5ba7..555655f02 100644
--- a/helper/osxkeychain/keychain.go
+++ b/helper/osxkeychain/keychain.go
@@ -1,3 +1,4 @@
+//go:build darwin && cgo
// +build darwin,cgo
package osxkeychain
diff --git a/helper/osxkeychain/osxkeychain.go b/helper/osxkeychain/osxkeychain.go
index cc0f951b0..93e2bcdf3 100644
--- a/helper/osxkeychain/osxkeychain.go
+++ b/helper/osxkeychain/osxkeychain.go
@@ -1,3 +1,4 @@
+//go:build darwin && cgo
// +build darwin,cgo
package osxkeychain
diff --git a/helper/osxkeychain/osxkeychain_test.go b/helper/osxkeychain/osxkeychain_test.go
index de9cda899..78b85337c 100644
--- a/helper/osxkeychain/osxkeychain_test.go
+++ b/helper/osxkeychain/osxkeychain_test.go
@@ -1,3 +1,4 @@
+//go:build darwin && cgo
// +build darwin,cgo
// Copyright (c) 2016 David Calavera
diff --git a/mocks/Page.go b/mocks/Page.go
new file mode 100644
index 000000000..ae182099a
--- /dev/null
+++ b/mocks/Page.go
@@ -0,0 +1,2132 @@
+// Code generated by mockery v2.22.1. DO NOT EDIT.
+
+package mocks
+
+import (
+ playwright "github.com/playwright-community/playwright-go"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// Page is an autogenerated mock type for the Page type
+type Page struct {
+ mock.Mock
+}
+
+// AddInitScript provides a mock function with given fields: script
+func (_m *Page) AddInitScript(script playwright.PageAddInitScriptOptions) error {
+ ret := _m.Called(script)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(playwright.PageAddInitScriptOptions) error); ok {
+ r0 = rf(script)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// AddScriptTag provides a mock function with given fields: options
+func (_m *Page) AddScriptTag(options playwright.PageAddScriptTagOptions) (playwright.ElementHandle, error) {
+ ret := _m.Called(options)
+
+ var r0 playwright.ElementHandle
+ var r1 error
+ if rf, ok := ret.Get(0).(func(playwright.PageAddScriptTagOptions) (playwright.ElementHandle, error)); ok {
+ return rf(options)
+ }
+ if rf, ok := ret.Get(0).(func(playwright.PageAddScriptTagOptions) playwright.ElementHandle); ok {
+ r0 = rf(options)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.ElementHandle)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(playwright.PageAddScriptTagOptions) error); ok {
+ r1 = rf(options)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// AddStyleTag provides a mock function with given fields: options
+func (_m *Page) AddStyleTag(options playwright.PageAddStyleTagOptions) (playwright.ElementHandle, error) {
+ ret := _m.Called(options)
+
+ var r0 playwright.ElementHandle
+ var r1 error
+ if rf, ok := ret.Get(0).(func(playwright.PageAddStyleTagOptions) (playwright.ElementHandle, error)); ok {
+ return rf(options)
+ }
+ if rf, ok := ret.Get(0).(func(playwright.PageAddStyleTagOptions) playwright.ElementHandle); ok {
+ r0 = rf(options)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.ElementHandle)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(playwright.PageAddStyleTagOptions) error); ok {
+ r1 = rf(options)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// BringToFront provides a mock function with given fields:
+func (_m *Page) BringToFront() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Check provides a mock function with given fields: selector, options
+func (_m *Page) Check(selector string, options ...playwright.FrameCheckOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameCheckOptions) error); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Click provides a mock function with given fields: selector, options
+func (_m *Page) Click(selector string, options ...playwright.PageClickOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageClickOptions) error); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Close provides a mock function with given fields: options
+func (_m *Page) Close(options ...playwright.PageCloseOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(...playwright.PageCloseOptions) error); ok {
+ r0 = rf(options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Content provides a mock function with given fields:
+func (_m *Page) Content() (string, error) {
+ ret := _m.Called()
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (string, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Context provides a mock function with given fields:
+func (_m *Page) Context() playwright.BrowserContext {
+ ret := _m.Called()
+
+ var r0 playwright.BrowserContext
+ if rf, ok := ret.Get(0).(func() playwright.BrowserContext); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.BrowserContext)
+ }
+ }
+
+ return r0
+}
+
+// Dblclick provides a mock function with given fields: expression, options
+func (_m *Page) Dblclick(expression string, options ...playwright.FrameDblclickOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, expression)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameDblclickOptions) error); ok {
+ r0 = rf(expression, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DispatchEvent provides a mock function with given fields: selector, typ, options
+func (_m *Page) DispatchEvent(selector string, typ string, options ...playwright.PageDispatchEventOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector, typ)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, string, ...playwright.PageDispatchEventOptions) error); ok {
+ r0 = rf(selector, typ, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DragAndDrop provides a mock function with given fields: source, target, options
+func (_m *Page) DragAndDrop(source string, target string, options ...playwright.FrameDragAndDropOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, source, target)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, string, ...playwright.FrameDragAndDropOptions) error); ok {
+ r0 = rf(source, target, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Emit provides a mock function with given fields: name, payload
+func (_m *Page) Emit(name string, payload ...interface{}) {
+ var _ca []interface{}
+ _ca = append(_ca, name)
+ _ca = append(_ca, payload...)
+ _m.Called(_ca...)
+}
+
+// EmulateMedia provides a mock function with given fields: options
+func (_m *Page) EmulateMedia(options ...playwright.PageEmulateMediaOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(...playwright.PageEmulateMediaOptions) error); ok {
+ r0 = rf(options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// EvalOnSelector provides a mock function with given fields: selector, expression, options
+func (_m *Page) EvalOnSelector(selector string, expression string, options ...interface{}) (interface{}, error) {
+ var _ca []interface{}
+ _ca = append(_ca, selector, expression)
+ _ca = append(_ca, options...)
+ ret := _m.Called(_ca...)
+
+ var r0 interface{}
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, string, ...interface{}) (interface{}, error)); ok {
+ return rf(selector, expression, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, string, ...interface{}) interface{}); ok {
+ r0 = rf(selector, expression, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(interface{})
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, string, ...interface{}) error); ok {
+ r1 = rf(selector, expression, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// EvalOnSelectorAll provides a mock function with given fields: selector, expression, options
+func (_m *Page) EvalOnSelectorAll(selector string, expression string, options ...interface{}) (interface{}, error) {
+ var _ca []interface{}
+ _ca = append(_ca, selector, expression)
+ _ca = append(_ca, options...)
+ ret := _m.Called(_ca...)
+
+ var r0 interface{}
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, string, ...interface{}) (interface{}, error)); ok {
+ return rf(selector, expression, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, string, ...interface{}) interface{}); ok {
+ r0 = rf(selector, expression, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(interface{})
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, string, ...interface{}) error); ok {
+ r1 = rf(selector, expression, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Evaluate provides a mock function with given fields: expression, options
+func (_m *Page) Evaluate(expression string, options ...interface{}) (interface{}, error) {
+ var _ca []interface{}
+ _ca = append(_ca, expression)
+ _ca = append(_ca, options...)
+ ret := _m.Called(_ca...)
+
+ var r0 interface{}
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...interface{}) (interface{}, error)); ok {
+ return rf(expression, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...interface{}) interface{}); ok {
+ r0 = rf(expression, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(interface{})
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...interface{}) error); ok {
+ r1 = rf(expression, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// EvaluateHandle provides a mock function with given fields: expression, options
+func (_m *Page) EvaluateHandle(expression string, options ...interface{}) (playwright.JSHandle, error) {
+ var _ca []interface{}
+ _ca = append(_ca, expression)
+ _ca = append(_ca, options...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.JSHandle
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...interface{}) (playwright.JSHandle, error)); ok {
+ return rf(expression, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...interface{}) playwright.JSHandle); ok {
+ r0 = rf(expression, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.JSHandle)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...interface{}) error); ok {
+ r1 = rf(expression, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectConsoleMessage provides a mock function with given fields: cb
+func (_m *Page) ExpectConsoleMessage(cb func() error) (playwright.ConsoleMessage, error) {
+ ret := _m.Called(cb)
+
+ var r0 playwright.ConsoleMessage
+ var r1 error
+ if rf, ok := ret.Get(0).(func(func() error) (playwright.ConsoleMessage, error)); ok {
+ return rf(cb)
+ }
+ if rf, ok := ret.Get(0).(func(func() error) playwright.ConsoleMessage); ok {
+ r0 = rf(cb)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.ConsoleMessage)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(func() error) error); ok {
+ r1 = rf(cb)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectDownload provides a mock function with given fields: cb
+func (_m *Page) ExpectDownload(cb func() error) (playwright.Download, error) {
+ ret := _m.Called(cb)
+
+ var r0 playwright.Download
+ var r1 error
+ if rf, ok := ret.Get(0).(func(func() error) (playwright.Download, error)); ok {
+ return rf(cb)
+ }
+ if rf, ok := ret.Get(0).(func(func() error) playwright.Download); ok {
+ r0 = rf(cb)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Download)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(func() error) error); ok {
+ r1 = rf(cb)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectEvent provides a mock function with given fields: event, cb, predicates
+func (_m *Page) ExpectEvent(event string, cb func() error, predicates ...interface{}) (interface{}, error) {
+ var _ca []interface{}
+ _ca = append(_ca, event, cb)
+ _ca = append(_ca, predicates...)
+ ret := _m.Called(_ca...)
+
+ var r0 interface{}
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, func() error, ...interface{}) (interface{}, error)); ok {
+ return rf(event, cb, predicates...)
+ }
+ if rf, ok := ret.Get(0).(func(string, func() error, ...interface{}) interface{}); ok {
+ r0 = rf(event, cb, predicates...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(interface{})
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, func() error, ...interface{}) error); ok {
+ r1 = rf(event, cb, predicates...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectFileChooser provides a mock function with given fields: cb
+func (_m *Page) ExpectFileChooser(cb func() error) (playwright.FileChooser, error) {
+ ret := _m.Called(cb)
+
+ var r0 playwright.FileChooser
+ var r1 error
+ if rf, ok := ret.Get(0).(func(func() error) (playwright.FileChooser, error)); ok {
+ return rf(cb)
+ }
+ if rf, ok := ret.Get(0).(func(func() error) playwright.FileChooser); ok {
+ r0 = rf(cb)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.FileChooser)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(func() error) error); ok {
+ r1 = rf(cb)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectLoadState provides a mock function with given fields: state, cb
+func (_m *Page) ExpectLoadState(state string, cb func() error) error {
+ ret := _m.Called(state, cb)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, func() error) error); ok {
+ r0 = rf(state, cb)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// ExpectNavigation provides a mock function with given fields: cb, options
+func (_m *Page) ExpectNavigation(cb func() error, options ...playwright.PageWaitForNavigationOptions) (playwright.Response, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, cb)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(func() error, ...playwright.PageWaitForNavigationOptions) (playwright.Response, error)); ok {
+ return rf(cb, options...)
+ }
+ if rf, ok := ret.Get(0).(func(func() error, ...playwright.PageWaitForNavigationOptions) playwright.Response); ok {
+ r0 = rf(cb, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(func() error, ...playwright.PageWaitForNavigationOptions) error); ok {
+ r1 = rf(cb, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectPopup provides a mock function with given fields: cb
+func (_m *Page) ExpectPopup(cb func() error) (playwright.Page, error) {
+ ret := _m.Called(cb)
+
+ var r0 playwright.Page
+ var r1 error
+ if rf, ok := ret.Get(0).(func(func() error) (playwright.Page, error)); ok {
+ return rf(cb)
+ }
+ if rf, ok := ret.Get(0).(func(func() error) playwright.Page); ok {
+ r0 = rf(cb)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Page)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(func() error) error); ok {
+ r1 = rf(cb)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectRequest provides a mock function with given fields: url, cb, options
+func (_m *Page) ExpectRequest(url interface{}, cb func() error, options ...interface{}) (playwright.Request, error) {
+ var _ca []interface{}
+ _ca = append(_ca, url, cb)
+ _ca = append(_ca, options...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Request
+ var r1 error
+ if rf, ok := ret.Get(0).(func(interface{}, func() error, ...interface{}) (playwright.Request, error)); ok {
+ return rf(url, cb, options...)
+ }
+ if rf, ok := ret.Get(0).(func(interface{}, func() error, ...interface{}) playwright.Request); ok {
+ r0 = rf(url, cb, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Request)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(interface{}, func() error, ...interface{}) error); ok {
+ r1 = rf(url, cb, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectResponse provides a mock function with given fields: url, cb, options
+func (_m *Page) ExpectResponse(url interface{}, cb func() error, options ...interface{}) (playwright.Response, error) {
+ var _ca []interface{}
+ _ca = append(_ca, url, cb)
+ _ca = append(_ca, options...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(interface{}, func() error, ...interface{}) (playwright.Response, error)); ok {
+ return rf(url, cb, options...)
+ }
+ if rf, ok := ret.Get(0).(func(interface{}, func() error, ...interface{}) playwright.Response); ok {
+ r0 = rf(url, cb, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(interface{}, func() error, ...interface{}) error); ok {
+ r1 = rf(url, cb, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectWorker provides a mock function with given fields: cb
+func (_m *Page) ExpectWorker(cb func() error) (playwright.Worker, error) {
+ ret := _m.Called(cb)
+
+ var r0 playwright.Worker
+ var r1 error
+ if rf, ok := ret.Get(0).(func(func() error) (playwright.Worker, error)); ok {
+ return rf(cb)
+ }
+ if rf, ok := ret.Get(0).(func(func() error) playwright.Worker); ok {
+ r0 = rf(cb)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Worker)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(func() error) error); ok {
+ r1 = rf(cb)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExpectedDialog provides a mock function with given fields: cb
+func (_m *Page) ExpectedDialog(cb func() error) (playwright.Dialog, error) {
+ ret := _m.Called(cb)
+
+ var r0 playwright.Dialog
+ var r1 error
+ if rf, ok := ret.Get(0).(func(func() error) (playwright.Dialog, error)); ok {
+ return rf(cb)
+ }
+ if rf, ok := ret.Get(0).(func(func() error) playwright.Dialog); ok {
+ r0 = rf(cb)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Dialog)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(func() error) error); ok {
+ r1 = rf(cb)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ExposeBinding provides a mock function with given fields: name, binding, handle
+func (_m *Page) ExposeBinding(name string, binding playwright.BindingCallFunction, handle ...bool) error {
+ _va := make([]interface{}, len(handle))
+ for _i := range handle {
+ _va[_i] = handle[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, name, binding)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, playwright.BindingCallFunction, ...bool) error); ok {
+ r0 = rf(name, binding, handle...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// ExposeFunction provides a mock function with given fields: name, binding
+func (_m *Page) ExposeFunction(name string, binding func(...interface{}) interface{}) error {
+ ret := _m.Called(name, binding)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, func(...interface{}) interface{}) error); ok {
+ r0 = rf(name, binding)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Fill provides a mock function with given fields: selector, text, options
+func (_m *Page) Fill(selector string, text string, options ...playwright.FrameFillOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector, text)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, string, ...playwright.FrameFillOptions) error); ok {
+ r0 = rf(selector, text, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Focus provides a mock function with given fields: expression, options
+func (_m *Page) Focus(expression string, options ...playwright.FrameFocusOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, expression)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameFocusOptions) error); ok {
+ r0 = rf(expression, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Frame provides a mock function with given fields: options
+func (_m *Page) Frame(options playwright.PageFrameOptions) playwright.Frame {
+ ret := _m.Called(options)
+
+ var r0 playwright.Frame
+ if rf, ok := ret.Get(0).(func(playwright.PageFrameOptions) playwright.Frame); ok {
+ r0 = rf(options)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Frame)
+ }
+ }
+
+ return r0
+}
+
+// Frames provides a mock function with given fields:
+func (_m *Page) Frames() []playwright.Frame {
+ ret := _m.Called()
+
+ var r0 []playwright.Frame
+ if rf, ok := ret.Get(0).(func() []playwright.Frame); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]playwright.Frame)
+ }
+ }
+
+ return r0
+}
+
+// GetAttribute provides a mock function with given fields: selector, name, options
+func (_m *Page) GetAttribute(selector string, name string, options ...playwright.PageGetAttributeOptions) (string, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector, name)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, string, ...playwright.PageGetAttributeOptions) (string, error)); ok {
+ return rf(selector, name, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, string, ...playwright.PageGetAttributeOptions) string); ok {
+ r0 = rf(selector, name, options...)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, string, ...playwright.PageGetAttributeOptions) error); ok {
+ r1 = rf(selector, name, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GoBack provides a mock function with given fields: options
+func (_m *Page) GoBack(options ...playwright.PageGoBackOptions) (playwright.Response, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(...playwright.PageGoBackOptions) (playwright.Response, error)); ok {
+ return rf(options...)
+ }
+ if rf, ok := ret.Get(0).(func(...playwright.PageGoBackOptions) playwright.Response); ok {
+ r0 = rf(options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(...playwright.PageGoBackOptions) error); ok {
+ r1 = rf(options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GoForward provides a mock function with given fields: options
+func (_m *Page) GoForward(options ...playwright.PageGoForwardOptions) (playwright.Response, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(...playwright.PageGoForwardOptions) (playwright.Response, error)); ok {
+ return rf(options...)
+ }
+ if rf, ok := ret.Get(0).(func(...playwright.PageGoForwardOptions) playwright.Response); ok {
+ r0 = rf(options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(...playwright.PageGoForwardOptions) error); ok {
+ r1 = rf(options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Goto provides a mock function with given fields: url, options
+func (_m *Page) Goto(url string, options ...playwright.PageGotoOptions) (playwright.Response, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, url)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageGotoOptions) (playwright.Response, error)); ok {
+ return rf(url, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageGotoOptions) playwright.Response); ok {
+ r0 = rf(url, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.PageGotoOptions) error); ok {
+ r1 = rf(url, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Hover provides a mock function with given fields: selector, options
+func (_m *Page) Hover(selector string, options ...playwright.PageHoverOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageHoverOptions) error); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// InnerHTML provides a mock function with given fields: selector, options
+func (_m *Page) InnerHTML(selector string, options ...playwright.PageInnerHTMLOptions) (string, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageInnerHTMLOptions) (string, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageInnerHTMLOptions) string); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.PageInnerHTMLOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// InnerText provides a mock function with given fields: selector, options
+func (_m *Page) InnerText(selector string, options ...playwright.PageInnerTextOptions) (string, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageInnerTextOptions) (string, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageInnerTextOptions) string); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.PageInnerTextOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// InputValue provides a mock function with given fields: selector, options
+func (_m *Page) InputValue(selector string, options ...playwright.FrameInputValueOptions) (string, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameInputValueOptions) (string, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameInputValueOptions) string); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.FrameInputValueOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// IsChecked provides a mock function with given fields: selector, options
+func (_m *Page) IsChecked(selector string, options ...playwright.FrameIsCheckedOptions) (bool, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsCheckedOptions) (bool, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsCheckedOptions) bool); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.FrameIsCheckedOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// IsClosed provides a mock function with given fields:
+func (_m *Page) IsClosed() bool {
+ ret := _m.Called()
+
+ var r0 bool
+ if rf, ok := ret.Get(0).(func() bool); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ return r0
+}
+
+// IsDisabled provides a mock function with given fields: selector, options
+func (_m *Page) IsDisabled(selector string, options ...playwright.FrameIsDisabledOptions) (bool, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsDisabledOptions) (bool, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsDisabledOptions) bool); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.FrameIsDisabledOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// IsEditable provides a mock function with given fields: selector, options
+func (_m *Page) IsEditable(selector string, options ...playwright.FrameIsEditableOptions) (bool, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsEditableOptions) (bool, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsEditableOptions) bool); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.FrameIsEditableOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// IsEnabled provides a mock function with given fields: selector, options
+func (_m *Page) IsEnabled(selector string, options ...playwright.FrameIsEnabledOptions) (bool, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsEnabledOptions) (bool, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsEnabledOptions) bool); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.FrameIsEnabledOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// IsHidden provides a mock function with given fields: selector, options
+func (_m *Page) IsHidden(selector string, options ...playwright.FrameIsHiddenOptions) (bool, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsHiddenOptions) (bool, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsHiddenOptions) bool); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.FrameIsHiddenOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// IsVisible provides a mock function with given fields: selector, options
+func (_m *Page) IsVisible(selector string, options ...playwright.FrameIsVisibleOptions) (bool, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsVisibleOptions) (bool, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameIsVisibleOptions) bool); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.FrameIsVisibleOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Keyboard provides a mock function with given fields:
+func (_m *Page) Keyboard() playwright.Keyboard {
+ ret := _m.Called()
+
+ var r0 playwright.Keyboard
+ if rf, ok := ret.Get(0).(func() playwright.Keyboard); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Keyboard)
+ }
+ }
+
+ return r0
+}
+
+// ListenerCount provides a mock function with given fields: name
+func (_m *Page) ListenerCount(name string) int {
+ ret := _m.Called(name)
+
+ var r0 int
+ if rf, ok := ret.Get(0).(func(string) int); ok {
+ r0 = rf(name)
+ } else {
+ r0 = ret.Get(0).(int)
+ }
+
+ return r0
+}
+
+// Locator provides a mock function with given fields: selector, options
+func (_m *Page) Locator(selector string, options ...playwright.PageLocatorOptions) (playwright.Locator, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Locator
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageLocatorOptions) (playwright.Locator, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageLocatorOptions) playwright.Locator); ok {
+ r0 = rf(selector, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Locator)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.PageLocatorOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// MainFrame provides a mock function with given fields:
+func (_m *Page) MainFrame() playwright.Frame {
+ ret := _m.Called()
+
+ var r0 playwright.Frame
+ if rf, ok := ret.Get(0).(func() playwright.Frame); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Frame)
+ }
+ }
+
+ return r0
+}
+
+// Mouse provides a mock function with given fields:
+func (_m *Page) Mouse() playwright.Mouse {
+ ret := _m.Called()
+
+ var r0 playwright.Mouse
+ if rf, ok := ret.Get(0).(func() playwright.Mouse); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Mouse)
+ }
+ }
+
+ return r0
+}
+
+// On provides a mock function with given fields: name, handler
+func (_m *Page) On(name string, handler interface{}) {
+ _m.Called(name, handler)
+}
+
+// Once provides a mock function with given fields: name, handler
+func (_m *Page) Once(name string, handler interface{}) {
+ _m.Called(name, handler)
+}
+
+// Opener provides a mock function with given fields:
+func (_m *Page) Opener() (playwright.Page, error) {
+ ret := _m.Called()
+
+ var r0 playwright.Page
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (playwright.Page, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() playwright.Page); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Page)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// PDF provides a mock function with given fields: options
+func (_m *Page) PDF(options ...playwright.PagePdfOptions) ([]byte, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 []byte
+ var r1 error
+ if rf, ok := ret.Get(0).(func(...playwright.PagePdfOptions) ([]byte, error)); ok {
+ return rf(options...)
+ }
+ if rf, ok := ret.Get(0).(func(...playwright.PagePdfOptions) []byte); ok {
+ r0 = rf(options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]byte)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(...playwright.PagePdfOptions) error); ok {
+ r1 = rf(options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Pause provides a mock function with given fields:
+func (_m *Page) Pause() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Press provides a mock function with given fields: selector, key, options
+func (_m *Page) Press(selector string, key string, options ...playwright.PagePressOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector, key)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, string, ...playwright.PagePressOptions) error); ok {
+ r0 = rf(selector, key, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// QuerySelector provides a mock function with given fields: selector
+func (_m *Page) QuerySelector(selector string) (playwright.ElementHandle, error) {
+ ret := _m.Called(selector)
+
+ var r0 playwright.ElementHandle
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string) (playwright.ElementHandle, error)); ok {
+ return rf(selector)
+ }
+ if rf, ok := ret.Get(0).(func(string) playwright.ElementHandle); ok {
+ r0 = rf(selector)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.ElementHandle)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(selector)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// QuerySelectorAll provides a mock function with given fields: selector
+func (_m *Page) QuerySelectorAll(selector string) ([]playwright.ElementHandle, error) {
+ ret := _m.Called(selector)
+
+ var r0 []playwright.ElementHandle
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string) ([]playwright.ElementHandle, error)); ok {
+ return rf(selector)
+ }
+ if rf, ok := ret.Get(0).(func(string) []playwright.ElementHandle); ok {
+ r0 = rf(selector)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]playwright.ElementHandle)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(selector)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Reload provides a mock function with given fields: options
+func (_m *Page) Reload(options ...playwright.PageReloadOptions) (playwright.Response, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(...playwright.PageReloadOptions) (playwright.Response, error)); ok {
+ return rf(options...)
+ }
+ if rf, ok := ret.Get(0).(func(...playwright.PageReloadOptions) playwright.Response); ok {
+ r0 = rf(options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(...playwright.PageReloadOptions) error); ok {
+ r1 = rf(options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// RemoveListener provides a mock function with given fields: name, handler
+func (_m *Page) RemoveListener(name string, handler interface{}) {
+ _m.Called(name, handler)
+}
+
+// Route provides a mock function with given fields: url, handler
+func (_m *Page) Route(url interface{}, handler func(playwright.Route, playwright.Request)) error {
+ ret := _m.Called(url, handler)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(interface{}, func(playwright.Route, playwright.Request)) error); ok {
+ r0 = rf(url, handler)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Screenshot provides a mock function with given fields: options
+func (_m *Page) Screenshot(options ...playwright.PageScreenshotOptions) ([]byte, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 []byte
+ var r1 error
+ if rf, ok := ret.Get(0).(func(...playwright.PageScreenshotOptions) ([]byte, error)); ok {
+ return rf(options...)
+ }
+ if rf, ok := ret.Get(0).(func(...playwright.PageScreenshotOptions) []byte); ok {
+ r0 = rf(options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]byte)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(...playwright.PageScreenshotOptions) error); ok {
+ r1 = rf(options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// SelectOption provides a mock function with given fields: selector, values, options
+func (_m *Page) SelectOption(selector string, values playwright.SelectOptionValues, options ...playwright.FrameSelectOptionOptions) ([]string, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector, values)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 []string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, playwright.SelectOptionValues, ...playwright.FrameSelectOptionOptions) ([]string, error)); ok {
+ return rf(selector, values, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, playwright.SelectOptionValues, ...playwright.FrameSelectOptionOptions) []string); ok {
+ r0 = rf(selector, values, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]string)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, playwright.SelectOptionValues, ...playwright.FrameSelectOptionOptions) error); ok {
+ r1 = rf(selector, values, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// SetChecked provides a mock function with given fields: selector, checked, options
+func (_m *Page) SetChecked(selector string, checked bool, options ...playwright.FrameSetCheckedOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector, checked)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, bool, ...playwright.FrameSetCheckedOptions) error); ok {
+ r0 = rf(selector, checked, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// SetContent provides a mock function with given fields: content, options
+func (_m *Page) SetContent(content string, options ...playwright.PageSetContentOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, content)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageSetContentOptions) error); ok {
+ r0 = rf(content, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// SetDefaultNavigationTimeout provides a mock function with given fields: timeout
+func (_m *Page) SetDefaultNavigationTimeout(timeout float64) {
+ _m.Called(timeout)
+}
+
+// SetDefaultTimeout provides a mock function with given fields: timeout
+func (_m *Page) SetDefaultTimeout(timeout float64) {
+ _m.Called(timeout)
+}
+
+// SetExtraHTTPHeaders provides a mock function with given fields: headers
+func (_m *Page) SetExtraHTTPHeaders(headers map[string]string) error {
+ ret := _m.Called(headers)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(map[string]string) error); ok {
+ r0 = rf(headers)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// SetInputFiles provides a mock function with given fields: selector, files, options
+func (_m *Page) SetInputFiles(selector string, files []playwright.InputFile, options ...playwright.FrameSetInputFilesOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector, files)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, []playwright.InputFile, ...playwright.FrameSetInputFilesOptions) error); ok {
+ r0 = rf(selector, files, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// SetViewportSize provides a mock function with given fields: width, height
+func (_m *Page) SetViewportSize(width int, height int) error {
+ ret := _m.Called(width, height)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(int, int) error); ok {
+ r0 = rf(width, height)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Tap provides a mock function with given fields: selector, options
+func (_m *Page) Tap(selector string, options ...playwright.FrameTapOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameTapOptions) error); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// TextContent provides a mock function with given fields: selector, options
+func (_m *Page) TextContent(selector string, options ...playwright.FrameTextContentOptions) (string, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameTextContentOptions) (string, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameTextContentOptions) string); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.FrameTextContentOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Title provides a mock function with given fields:
+func (_m *Page) Title() (string, error) {
+ ret := _m.Called()
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (string, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Touchscreen provides a mock function with given fields:
+func (_m *Page) Touchscreen() playwright.Touchscreen {
+ ret := _m.Called()
+
+ var r0 playwright.Touchscreen
+ if rf, ok := ret.Get(0).(func() playwright.Touchscreen); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Touchscreen)
+ }
+ }
+
+ return r0
+}
+
+// Type provides a mock function with given fields: selector, text, options
+func (_m *Page) Type(selector string, text string, options ...playwright.PageTypeOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector, text)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, string, ...playwright.PageTypeOptions) error); ok {
+ r0 = rf(selector, text, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// URL provides a mock function with given fields:
+func (_m *Page) URL() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// Uncheck provides a mock function with given fields: selector, options
+func (_m *Page) Uncheck(selector string, options ...playwright.FrameUncheckOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameUncheckOptions) error); ok {
+ r0 = rf(selector, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Unroute provides a mock function with given fields: url, handler
+func (_m *Page) Unroute(url interface{}, handler ...func(playwright.Route, playwright.Request)) error {
+ _va := make([]interface{}, len(handler))
+ for _i := range handler {
+ _va[_i] = handler[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, url)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(interface{}, ...func(playwright.Route, playwright.Request)) error); ok {
+ r0 = rf(url, handler...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Video provides a mock function with given fields:
+func (_m *Page) Video() playwright.Video {
+ ret := _m.Called()
+
+ var r0 playwright.Video
+ if rf, ok := ret.Get(0).(func() playwright.Video); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Video)
+ }
+ }
+
+ return r0
+}
+
+// ViewportSize provides a mock function with given fields:
+func (_m *Page) ViewportSize() playwright.ViewportSize {
+ ret := _m.Called()
+
+ var r0 playwright.ViewportSize
+ if rf, ok := ret.Get(0).(func() playwright.ViewportSize); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(playwright.ViewportSize)
+ }
+
+ return r0
+}
+
+// WaitForEvent provides a mock function with given fields: event, predicate
+func (_m *Page) WaitForEvent(event string, predicate ...interface{}) interface{} {
+ var _ca []interface{}
+ _ca = append(_ca, event)
+ _ca = append(_ca, predicate...)
+ ret := _m.Called(_ca...)
+
+ var r0 interface{}
+ if rf, ok := ret.Get(0).(func(string, ...interface{}) interface{}); ok {
+ r0 = rf(event, predicate...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(interface{})
+ }
+ }
+
+ return r0
+}
+
+// WaitForFunction provides a mock function with given fields: expression, arg, options
+func (_m *Page) WaitForFunction(expression string, arg interface{}, options ...playwright.FrameWaitForFunctionOptions) (playwright.JSHandle, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, expression, arg)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.JSHandle
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, interface{}, ...playwright.FrameWaitForFunctionOptions) (playwright.JSHandle, error)); ok {
+ return rf(expression, arg, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, interface{}, ...playwright.FrameWaitForFunctionOptions) playwright.JSHandle); ok {
+ r0 = rf(expression, arg, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.JSHandle)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, interface{}, ...playwright.FrameWaitForFunctionOptions) error); ok {
+ r1 = rf(expression, arg, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// WaitForLoadState provides a mock function with given fields: state
+func (_m *Page) WaitForLoadState(state ...string) {
+ _va := make([]interface{}, len(state))
+ for _i := range state {
+ _va[_i] = state[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ _m.Called(_ca...)
+}
+
+// WaitForNavigation provides a mock function with given fields: options
+func (_m *Page) WaitForNavigation(options ...playwright.PageWaitForNavigationOptions) (playwright.Response, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func(...playwright.PageWaitForNavigationOptions) (playwright.Response, error)); ok {
+ return rf(options...)
+ }
+ if rf, ok := ret.Get(0).(func(...playwright.PageWaitForNavigationOptions) playwright.Response); ok {
+ r0 = rf(options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(...playwright.PageWaitForNavigationOptions) error); ok {
+ r1 = rf(options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// WaitForRequest provides a mock function with given fields: url, options
+func (_m *Page) WaitForRequest(url interface{}, options ...interface{}) playwright.Request {
+ var _ca []interface{}
+ _ca = append(_ca, url)
+ _ca = append(_ca, options...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Request
+ if rf, ok := ret.Get(0).(func(interface{}, ...interface{}) playwright.Request); ok {
+ r0 = rf(url, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Request)
+ }
+ }
+
+ return r0
+}
+
+// WaitForResponse provides a mock function with given fields: url, options
+func (_m *Page) WaitForResponse(url interface{}, options ...interface{}) playwright.Response {
+ var _ca []interface{}
+ _ca = append(_ca, url)
+ _ca = append(_ca, options...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.Response
+ if rf, ok := ret.Get(0).(func(interface{}, ...interface{}) playwright.Response); ok {
+ r0 = rf(url, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ return r0
+}
+
+// WaitForSelector provides a mock function with given fields: selector, options
+func (_m *Page) WaitForSelector(selector string, options ...playwright.PageWaitForSelectorOptions) (playwright.ElementHandle, error) {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, selector)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 playwright.ElementHandle
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageWaitForSelectorOptions) (playwright.ElementHandle, error)); ok {
+ return rf(selector, options...)
+ }
+ if rf, ok := ret.Get(0).(func(string, ...playwright.PageWaitForSelectorOptions) playwright.ElementHandle); ok {
+ r0 = rf(selector, options...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.ElementHandle)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string, ...playwright.PageWaitForSelectorOptions) error); ok {
+ r1 = rf(selector, options...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// WaitForTimeout provides a mock function with given fields: timeout
+func (_m *Page) WaitForTimeout(timeout float64) {
+ _m.Called(timeout)
+}
+
+// WaitForURL provides a mock function with given fields: url, options
+func (_m *Page) WaitForURL(url string, options ...playwright.FrameWaitForURLOptions) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, url)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(string, ...playwright.FrameWaitForURLOptions) error); ok {
+ r0 = rf(url, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Workers provides a mock function with given fields:
+func (_m *Page) Workers() []playwright.Worker {
+ ret := _m.Called()
+
+ var r0 []playwright.Worker
+ if rf, ok := ret.Get(0).(func() []playwright.Worker); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]playwright.Worker)
+ }
+ }
+
+ return r0
+}
+
+type mockConstructorTestingTNewPage interface {
+ mock.TestingT
+ Cleanup(func())
+}
+
+// NewPage creates a new instance of Page. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewPage(t mockConstructorTestingTNewPage) *Page {
+ mock := &Page{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/mocks/Request.go b/mocks/Request.go
new file mode 100644
index 000000000..9c0233e4c
--- /dev/null
+++ b/mocks/Request.go
@@ -0,0 +1,398 @@
+// Code generated by mockery v2.22.1. DO NOT EDIT.
+
+package mocks
+
+import (
+ playwright "github.com/playwright-community/playwright-go"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// Request is an autogenerated mock type for the Request type
+type Request struct {
+ mock.Mock
+}
+
+// AllHeaders provides a mock function with given fields:
+func (_m *Request) AllHeaders() (map[string]string, error) {
+ ret := _m.Called()
+
+ var r0 map[string]string
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (map[string]string, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() map[string]string); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(map[string]string)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Failure provides a mock function with given fields:
+func (_m *Request) Failure() *playwright.RequestFailure {
+ ret := _m.Called()
+
+ var r0 *playwright.RequestFailure
+ if rf, ok := ret.Get(0).(func() *playwright.RequestFailure); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*playwright.RequestFailure)
+ }
+ }
+
+ return r0
+}
+
+// Frame provides a mock function with given fields:
+func (_m *Request) Frame() playwright.Frame {
+ ret := _m.Called()
+
+ var r0 playwright.Frame
+ if rf, ok := ret.Get(0).(func() playwright.Frame); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Frame)
+ }
+ }
+
+ return r0
+}
+
+// HeaderValue provides a mock function with given fields: name
+func (_m *Request) HeaderValue(name string) (string, error) {
+ ret := _m.Called(name)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
+ return rf(name)
+ }
+ if rf, ok := ret.Get(0).(func(string) string); ok {
+ r0 = rf(name)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// HeaderValues provides a mock function with given fields: name
+func (_m *Request) HeaderValues(name string) ([]string, error) {
+ ret := _m.Called(name)
+
+ var r0 []string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string) ([]string, error)); ok {
+ return rf(name)
+ }
+ if rf, ok := ret.Get(0).(func(string) []string); ok {
+ r0 = rf(name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]string)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Headers provides a mock function with given fields:
+func (_m *Request) Headers() map[string]string {
+ ret := _m.Called()
+
+ var r0 map[string]string
+ if rf, ok := ret.Get(0).(func() map[string]string); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(map[string]string)
+ }
+ }
+
+ return r0
+}
+
+// HeadersArray provides a mock function with given fields:
+func (_m *Request) HeadersArray() (playwright.HeadersArray, error) {
+ ret := _m.Called()
+
+ var r0 playwright.HeadersArray
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (playwright.HeadersArray, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() playwright.HeadersArray); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.HeadersArray)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// IsNavigationRequest provides a mock function with given fields:
+func (_m *Request) IsNavigationRequest() bool {
+ ret := _m.Called()
+
+ var r0 bool
+ if rf, ok := ret.Get(0).(func() bool); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ return r0
+}
+
+// Method provides a mock function with given fields:
+func (_m *Request) Method() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// PostData provides a mock function with given fields:
+func (_m *Request) PostData() (string, error) {
+ ret := _m.Called()
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (string, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// PostDataBuffer provides a mock function with given fields:
+func (_m *Request) PostDataBuffer() ([]byte, error) {
+ ret := _m.Called()
+
+ var r0 []byte
+ var r1 error
+ if rf, ok := ret.Get(0).(func() ([]byte, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() []byte); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]byte)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// PostDataJSON provides a mock function with given fields: v
+func (_m *Request) PostDataJSON(v interface{}) error {
+ ret := _m.Called(v)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(interface{}) error); ok {
+ r0 = rf(v)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// RedirectedFrom provides a mock function with given fields:
+func (_m *Request) RedirectedFrom() playwright.Request {
+ ret := _m.Called()
+
+ var r0 playwright.Request
+ if rf, ok := ret.Get(0).(func() playwright.Request); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Request)
+ }
+ }
+
+ return r0
+}
+
+// RedirectedTo provides a mock function with given fields:
+func (_m *Request) RedirectedTo() playwright.Request {
+ ret := _m.Called()
+
+ var r0 playwright.Request
+ if rf, ok := ret.Get(0).(func() playwright.Request); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Request)
+ }
+ }
+
+ return r0
+}
+
+// ResourceType provides a mock function with given fields:
+func (_m *Request) ResourceType() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// Response provides a mock function with given fields:
+func (_m *Request) Response() (playwright.Response, error) {
+ ret := _m.Called()
+
+ var r0 playwright.Response
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (playwright.Response, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() playwright.Response); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Response)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Sizes provides a mock function with given fields:
+func (_m *Request) Sizes() (*playwright.RequestSizesResult, error) {
+ ret := _m.Called()
+
+ var r0 *playwright.RequestSizesResult
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (*playwright.RequestSizesResult, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() *playwright.RequestSizesResult); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*playwright.RequestSizesResult)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Timing provides a mock function with given fields:
+func (_m *Request) Timing() *playwright.ResourceTiming {
+ ret := _m.Called()
+
+ var r0 *playwright.ResourceTiming
+ if rf, ok := ret.Get(0).(func() *playwright.ResourceTiming); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*playwright.ResourceTiming)
+ }
+ }
+
+ return r0
+}
+
+// URL provides a mock function with given fields:
+func (_m *Request) URL() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+type mockConstructorTestingTNewRequest interface {
+ mock.TestingT
+ Cleanup(func())
+}
+
+// NewRequest creates a new instance of Request. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewRequest(t mockConstructorTestingTNewRequest) *Request {
+ mock := &Request{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/mocks/Response.go b/mocks/Response.go
new file mode 100644
index 000000000..48fa44d44
--- /dev/null
+++ b/mocks/Response.go
@@ -0,0 +1,355 @@
+// Code generated by mockery v2.22.1. DO NOT EDIT.
+
+package mocks
+
+import (
+ playwright "github.com/playwright-community/playwright-go"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// Response is an autogenerated mock type for the Response type
+type Response struct {
+ mock.Mock
+}
+
+// AllHeaders provides a mock function with given fields:
+func (_m *Response) AllHeaders() (map[string]string, error) {
+ ret := _m.Called()
+
+ var r0 map[string]string
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (map[string]string, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() map[string]string); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(map[string]string)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Body provides a mock function with given fields:
+func (_m *Response) Body() ([]byte, error) {
+ ret := _m.Called()
+
+ var r0 []byte
+ var r1 error
+ if rf, ok := ret.Get(0).(func() ([]byte, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() []byte); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]byte)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Finished provides a mock function with given fields:
+func (_m *Response) Finished() {
+ _m.Called()
+}
+
+// Frame provides a mock function with given fields:
+func (_m *Response) Frame() playwright.Frame {
+ ret := _m.Called()
+
+ var r0 playwright.Frame
+ if rf, ok := ret.Get(0).(func() playwright.Frame); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Frame)
+ }
+ }
+
+ return r0
+}
+
+// HeaderValue provides a mock function with given fields: name
+func (_m *Response) HeaderValue(name string) (string, error) {
+ ret := _m.Called(name)
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
+ return rf(name)
+ }
+ if rf, ok := ret.Get(0).(func(string) string); ok {
+ r0 = rf(name)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// HeaderValues provides a mock function with given fields: name
+func (_m *Response) HeaderValues(name string) ([]string, error) {
+ ret := _m.Called(name)
+
+ var r0 []string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(string) ([]string, error)); ok {
+ return rf(name)
+ }
+ if rf, ok := ret.Get(0).(func(string) []string); ok {
+ r0 = rf(name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]string)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Headers provides a mock function with given fields:
+func (_m *Response) Headers() map[string]string {
+ ret := _m.Called()
+
+ var r0 map[string]string
+ if rf, ok := ret.Get(0).(func() map[string]string); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(map[string]string)
+ }
+ }
+
+ return r0
+}
+
+// HeadersArray provides a mock function with given fields:
+func (_m *Response) HeadersArray() (playwright.HeadersArray, error) {
+ ret := _m.Called()
+
+ var r0 playwright.HeadersArray
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (playwright.HeadersArray, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() playwright.HeadersArray); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.HeadersArray)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// JSON provides a mock function with given fields: v
+func (_m *Response) JSON(v interface{}) error {
+ ret := _m.Called(v)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(interface{}) error); ok {
+ r0 = rf(v)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Ok provides a mock function with given fields:
+func (_m *Response) Ok() bool {
+ ret := _m.Called()
+
+ var r0 bool
+ if rf, ok := ret.Get(0).(func() bool); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ return r0
+}
+
+// Request provides a mock function with given fields:
+func (_m *Response) Request() playwright.Request {
+ ret := _m.Called()
+
+ var r0 playwright.Request
+ if rf, ok := ret.Get(0).(func() playwright.Request); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(playwright.Request)
+ }
+ }
+
+ return r0
+}
+
+// SecurityDetails provides a mock function with given fields:
+func (_m *Response) SecurityDetails() (*playwright.ResponseSecurityDetailsResult, error) {
+ ret := _m.Called()
+
+ var r0 *playwright.ResponseSecurityDetailsResult
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (*playwright.ResponseSecurityDetailsResult, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() *playwright.ResponseSecurityDetailsResult); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*playwright.ResponseSecurityDetailsResult)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ServerAddr provides a mock function with given fields:
+func (_m *Response) ServerAddr() (*playwright.ResponseServerAddrResult, error) {
+ ret := _m.Called()
+
+ var r0 *playwright.ResponseServerAddrResult
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (*playwright.ResponseServerAddrResult, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() *playwright.ResponseServerAddrResult); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*playwright.ResponseServerAddrResult)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Status provides a mock function with given fields:
+func (_m *Response) Status() int {
+ ret := _m.Called()
+
+ var r0 int
+ if rf, ok := ret.Get(0).(func() int); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(int)
+ }
+
+ return r0
+}
+
+// StatusText provides a mock function with given fields:
+func (_m *Response) StatusText() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// Text provides a mock function with given fields:
+func (_m *Response) Text() (string, error) {
+ ret := _m.Called()
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func() (string, error)); ok {
+ return rf()
+ }
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// URL provides a mock function with given fields:
+func (_m *Response) URL() string {
+ ret := _m.Called()
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+type mockConstructorTestingTNewResponse interface {
+ mock.TestingT
+ Cleanup(func())
+}
+
+// NewResponse creates a new instance of Response. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewResponse(t mockConstructorTestingTNewResponse) *Response {
+ mock := &Response{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/pkg/awsconfig/awsconfig.go b/pkg/awsconfig/awsconfig.go
index 4d7317b19..b1bfef9dc 100644
--- a/pkg/awsconfig/awsconfig.go
+++ b/pkg/awsconfig/awsconfig.go
@@ -1,7 +1,6 @@
package awsconfig
import (
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -143,7 +142,7 @@ func (p *CredentialsProvider) ensureConfigExists() error {
logger.WithField("dir", dir).Debug("Dir created")
// create an base config file
- err = ioutil.WriteFile(filename, []byte("["+p.Profile+"]"), 0600)
+ err = os.WriteFile(filename, []byte("["+p.Profile+"]"), 0600)
if err != nil {
return err
}
diff --git a/pkg/cfg/cfg.go b/pkg/cfg/cfg.go
index ccfb19cc4..d547edf78 100644
--- a/pkg/cfg/cfg.go
+++ b/pkg/cfg/cfg.go
@@ -40,6 +40,7 @@ type IDPAccount struct {
Username string `ini:"username"`
Provider string `ini:"provider"`
MFA string `ini:"mfa"`
+ MFAIPAddress string `ini:"mfa_ip_address"` // used by OneLogin
SkipVerify bool `ini:"skip_verify"`
Timeout int `ini:"timeout"`
AmazonWebservicesURN string `ini:"aws_urn"`
@@ -55,8 +56,11 @@ type IDPAccount struct {
SAMLCache bool `ini:"saml_cache"`
SAMLCacheFile string `ini:"saml_cache_file"`
TargetURL string `ini:"target_url"`
- DisableRememberDevice bool `ini:"disable_remember_device"` // used by Okta
- DisableSessions bool `ini:"disable_sessions"` // used by Okta
+ DisableRememberDevice bool `ini:"disable_remember_device"` // used by Okta
+ DisableSessions bool `ini:"disable_sessions"` // used by Okta
+ DownloadBrowser bool `ini:"download_browser_driver"` // used by browser
+ BrowserDriverDir string `ini:"browser_driver_dir,omitempty"` // used by browser; hide from user if not set
+ Headless bool `ini:"headless"` // used by browser
Prompter string `ini:"prompter"`
}
diff --git a/pkg/cfg/cfg_test.go b/pkg/cfg/cfg_test.go
index b42802474..5a32a5c37 100644
--- a/pkg/cfg/cfg_test.go
+++ b/pkg/cfg/cfg_test.go
@@ -13,8 +13,28 @@ func TestNewConfigManagerNew(t *testing.T) {
cfgm, err := NewConfigManager("example/saml2aws.ini")
require.Nil(t, err)
+ require.NotNil(t, cfgm)
+}
+
+func TestIDPAccountString(t *testing.T) {
+ cfgm, err := NewConfigManager("example/saml2aws.ini")
+ require.Nil(t, err)
require.NotNil(t, cfgm)
+
+ idpAccount, err := cfgm.LoadIDPAccount("test123")
+ require.Nil(t, err)
+ s := idpAccount.String()
+ require.Contains(t, s, "urn:amazon:webservices\n")
+}
+
+func TestNewConfigManagerDefaultEmpty(t *testing.T) {
+ cfgm, err := NewConfigManager("")
+ require.Nil(t, err)
+ require.Contains(t, cfgm.configPath, ".saml2aws")
+ idpAccount, err := cfgm.LoadIDPAccount("foo")
+ require.Nil(t, err)
+ require.Equal(t, idpAccount.URL, "")
}
func TestNewConfigManagerLoad(t *testing.T) {
diff --git a/pkg/cookiejar/jar.go b/pkg/cookiejar/jar.go
index 62e5b26ec..2c3b569f8 100644
--- a/pkg/cookiejar/jar.go
+++ b/pkg/cookiejar/jar.go
@@ -18,9 +18,9 @@ import (
)
// PublicSuffixList provides the public suffix of a domain. For example:
-// - the public suffix of "example.com" is "com",
-// - the public suffix of "foo1.foo2.foo3.co.uk" is "co.uk", and
-// - the public suffix of "bar.pvt.k12.ma.us" is "pvt.k12.ma.us".
+// - the public suffix of "example.com" is "com",
+// - the public suffix of "foo1.foo2.foo3.co.uk" is "co.uk", and
+// - the public suffix of "bar.pvt.k12.ma.us" is "pvt.k12.ma.us".
//
// Implementations of PublicSuffixList must be safe for concurrent use by
// multiple goroutines.
diff --git a/pkg/cookiejar/jar_test.go b/pkg/cookiejar/jar_test.go
index fc1462d0d..5262d2154 100644
--- a/pkg/cookiejar/jar_test.go
+++ b/pkg/cookiejar/jar_test.go
@@ -20,8 +20,9 @@ var tNow = time.Date(2013, 1, 1, 12, 0, 0, 0, time.UTC)
// testPSL implements PublicSuffixList with just two rules: "co.uk"
// and the default rule "*".
// The implementation has two intentional bugs:
-// PublicSuffix("www.buggy.psl") == "xy"
-// PublicSuffix("www2.buggy.psl") == "com"
+//
+// PublicSuffix("www.buggy.psl") == "xy"
+// PublicSuffix("www2.buggy.psl") == "com"
type testPSL struct{}
func (testPSL) String() string {
@@ -358,13 +359,13 @@ func mustParseURL(s string) *url.URL {
}
// jarTest encapsulates the following actions on a jar:
-// 1. Perform SetCookies with fromURL and the cookies from setCookies.
-// (Done at time tNow + 0 ms.)
-// 2. Check that the entries in the jar matches content.
-// (Done at time tNow + 1001 ms.)
-// 3. For each query in tests: Check that Cookies with toURL yields the
-// cookies in want.
-// (Query n done at tNow + (n+2)*1001 ms.)
+// 1. Perform SetCookies with fromURL and the cookies from setCookies.
+// (Done at time tNow + 0 ms.)
+// 2. Check that the entries in the jar matches content.
+// (Done at time tNow + 1001 ms.)
+// 3. For each query in tests: Check that Cookies with toURL yields the
+// cookies in want.
+// (Query n done at tNow + (n+2)*1001 ms.)
type jarTest struct {
description string // The description of what this test is supposed to test
fromURL string // The full URL of the request from which Set-Cookie headers where received
diff --git a/pkg/creds/creds.go b/pkg/creds/creds.go
index e006216ba..5aa697103 100644
--- a/pkg/creds/creds.go
+++ b/pkg/creds/creds.go
@@ -4,6 +4,8 @@ package creds
type LoginDetails struct {
ClientID string // used by OneLogin
ClientSecret string // used by OneLogin
+ DownloadBrowser bool // used by Browser
+ MFAIPAddress string // used by OneLogin
Username string
Password string
MFAToken string
diff --git a/pkg/flags/flags.go b/pkg/flags/flags.go
index 7a3beb6fa..60d86408a 100644
--- a/pkg/flags/flags.go
+++ b/pkg/flags/flags.go
@@ -13,6 +13,7 @@ type CommonFlags struct {
IdpAccount string
IdpProvider string
MFA string
+ MFAIPAddress string
MFAToken string
URL string
Username string
@@ -38,6 +39,7 @@ type CommonFlags struct {
// LoginExecFlags flags for the Login / Exec commands
type LoginExecFlags struct {
CommonFlags *CommonFlags
+ DownloadBrowser bool
Force bool
DuoMFAOption string
ExecProfile string
@@ -75,6 +77,10 @@ func ApplyFlagOverrides(commonFlags *CommonFlags, account *cfg.IDPAccount) {
account.MFA = commonFlags.MFA
}
+ if commonFlags.MFAIPAddress != "" {
+ account.MFAIPAddress = commonFlags.MFAIPAddress
+ }
+
if commonFlags.AmazonWebservicesURN != "" {
account.AmazonWebservicesURN = commonFlags.AmazonWebservicesURN
}
diff --git a/pkg/page/form_test.go b/pkg/page/form_test.go
index 8b0656edc..00bfcdf3a 100644
--- a/pkg/page/form_test.go
+++ b/pkg/page/form_test.go
@@ -2,8 +2,8 @@ package page
import (
"bytes"
- "io/ioutil"
"net/url"
+ "os"
"testing"
"github.com/PuerkitoBio/goquery"
@@ -11,7 +11,7 @@ import (
)
func TestNewFormFromDocument(t *testing.T) {
- data, err := ioutil.ReadFile("example/multi-form.html")
+ data, err := os.ReadFile("example/multi-form.html")
require.Nil(t, err)
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(data))
diff --git a/pkg/provider/aad/aad.go b/pkg/provider/aad/aad.go
index 0c2607097..0bfb8121f 100644
--- a/pkg/provider/aad/aad.go
+++ b/pkg/provider/aad/aad.go
@@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"log"
"net/http"
"net/url"
@@ -15,13 +14,16 @@ import (
"github.com/PuerkitoBio/goquery"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+
"github.com/versent/saml2aws/v2/pkg/cfg"
"github.com/versent/saml2aws/v2/pkg/creds"
"github.com/versent/saml2aws/v2/pkg/prompter"
"github.com/versent/saml2aws/v2/pkg/provider"
- "golang.org/x/net/html"
)
+var logger = logrus.WithField("provider", "AzureAD")
+
// Client wrapper around AzureAD enabling authentication and retrieval of assertions
type Client struct {
provider.ValidateBase
@@ -30,440 +32,76 @@ type Client struct {
idpAccount *cfg.IDPAccount
}
-// Autogenerate startSAML Response struct
-// some case, some fields is not exists
-type startSAMLResponse struct {
- FShowPersistentCookiesWarning bool `json:"fShowPersistentCookiesWarning"`
- URLMsaLogout string `json:"urlMsaLogout"`
- ShowCantAccessAccountLink bool `json:"showCantAccessAccountLink"`
- URLGitHubFed string `json:"urlGitHubFed"`
- FShowSignInWithGitHubOnlyOnCredPicker bool `json:"fShowSignInWithGitHubOnlyOnCredPicker"`
- FEnableShowResendCode bool `json:"fEnableShowResendCode"`
- IShowResendCodeDelay int `json:"iShowResendCodeDelay"`
- SSMSCtryPhoneData string `json:"sSMSCtryPhoneData"`
- FUseInlinePhoneNumber bool `json:"fUseInlinePhoneNumber"`
- URLSessionState string `json:"urlSessionState"`
- URLResetPassword string `json:"urlResetPassword"`
- URLMsaResetPassword string `json:"urlMsaResetPassword"`
- URLLogin string `json:"urlLogin"`
- URLSignUp string `json:"urlSignUp"`
- URLGetCredentialType string `json:"urlGetCredentialType"`
- URLGetOneTimeCode string `json:"urlGetOneTimeCode"`
- URLLogout string `json:"urlLogout"`
- URLForget string `json:"urlForget"`
- URLDisambigRename string `json:"urlDisambigRename"`
- URLGoToAADError string `json:"urlGoToAADError"`
- URLDssoStatus string `json:"urlDssoStatus"`
- URLFidoHelp string `json:"urlFidoHelp"`
- URLFidoLogin string `json:"urlFidoLogin"`
- URLPostAad string `json:"urlPostAad"`
- URLPostMsa string `json:"urlPostMsa"`
- URLPIAEndAuth string `json:"urlPIAEndAuth"`
- FCBShowSignUp bool `json:"fCBShowSignUp"`
- FKMSIEnabled bool `json:"fKMSIEnabled"`
- ILoginMode int `json:"iLoginMode"`
- FAllowPhoneSignIn bool `json:"fAllowPhoneSignIn"`
- FAllowPhoneInput bool `json:"fAllowPhoneInput"`
- FAllowSkypeNameLogin bool `json:"fAllowSkypeNameLogin"`
- IMaxPollErrors int `json:"iMaxPollErrors"`
- IPollingTimeout int `json:"iPollingTimeout"`
- SrsSuccess bool `json:"srsSuccess"`
- FShowSwitchUser bool `json:"fShowSwitchUser"`
- ArrValErrs []string `json:"arrValErrs"`
- SErrorCode string `json:"sErrorCode"`
- SErrTxt string `json:"sErrTxt"`
- SResetPasswordPrefillParam string `json:"sResetPasswordPrefillParam"`
- OnPremPasswordValidationConfig struct {
- IsUserRealmPrecheckEnabled bool `json:"isUserRealmPrecheckEnabled"`
- } `json:"onPremPasswordValidationConfig"`
- FSwitchDisambig bool `json:"fSwitchDisambig"`
- OCancelPostParams struct {
- Error string `json:"error"`
- ErrorSubcode string `json:"error_subcode"`
- State string `json:"state"`
- } `json:"oCancelPostParams"`
- IAllowedIdentities int `json:"iAllowedIdentities"`
- IRemoteNgcPollingType int `json:"iRemoteNgcPollingType"`
- IsGlobalTenant bool `json:"isGlobalTenant"`
- FIsFidoSupported bool `json:"fIsFidoSupported"`
- FUseNewNoPasswordTypes bool `json:"fUseNewNoPasswordTypes"`
- IMaxStackForKnockoutAsyncComponents int `json:"iMaxStackForKnockoutAsyncComponents"`
- StrCopyrightTxt string `json:"strCopyrightTxt"`
- FShowButtons bool `json:"fShowButtons"`
- URLCdn string `json:"urlCdn"`
- URLFooterTOU string `json:"urlFooterTOU"`
- URLFooterPrivacy string `json:"urlFooterPrivacy"`
- URLPost string `json:"urlPost"`
- URLRefresh string `json:"urlRefresh"`
- URLCancel string `json:"urlCancel"`
- IPawnIcon int `json:"iPawnIcon"`
- IPollingInterval int `json:"iPollingInterval"`
- SPOSTUsername string `json:"sPOST_Username"`
- SFT string `json:"sFT"`
- SFTName string `json:"sFTName"`
- SSessionIdentifierName string `json:"sSessionIdentifierName"`
- SCtx string `json:"sCtx"`
- IProductIcon int `json:"iProductIcon"`
- URLReportPageLoad string `json:"urlReportPageLoad"`
- StaticTenantBranding interface{} `json:"staticTenantBranding"`
- OAppCobranding struct {
- } `json:"oAppCobranding"`
- IBackgroundImage int `json:"iBackgroundImage"`
- ArrSessions []interface{} `json:"arrSessions"`
- FUseConstantPolling bool `json:"fUseConstantPolling"`
- FUseFlowTokenAsCanary bool `json:"fUseFlowTokenAsCanary"`
- FApplicationInsightsEnabled bool `json:"fApplicationInsightsEnabled"`
- IApplicationInsightsEnabledPercentage int `json:"iApplicationInsightsEnabledPercentage"`
- URLSetDebugMode string `json:"urlSetDebugMode"`
- FEnableCSSAnimation bool `json:"fEnableCssAnimation"`
- FAllowGrayOutLightBox bool `json:"fAllowGrayOutLightBox"`
- FIsRemoteNGCSupported bool `json:"fIsRemoteNGCSupported"`
- Scid int `json:"scid"`
- Hpgact int `json:"hpgact"`
- Hpgid int `json:"hpgid"`
- Pgid string `json:"pgid"`
- APICanary string `json:"apiCanary"`
- Canary string `json:"canary"`
- CorrelationID string `json:"correlationId"`
- SessionID string `json:"sessionId"`
- Locale struct {
- Mkt string `json:"mkt"`
- Lcid int `json:"lcid"`
- } `json:"locale"`
- SlMaxRetry int `json:"slMaxRetry"`
- SlReportFailure bool `json:"slReportFailure"`
- Strings struct {
- Desktopsso struct {
- Authenticatingmessage string `json:"authenticatingmessage"`
- } `json:"desktopsso"`
- } `json:"strings"`
- Enums struct {
- ClientMetricsModes struct {
- None int `json:"None"`
- SubmitOnPost int `json:"SubmitOnPost"`
- SubmitOnRedirect int `json:"SubmitOnRedirect"`
- InstrumentPlt int `json:"InstrumentPlt"`
- } `json:"ClientMetricsModes"`
- } `json:"enums"`
- Urls struct {
- Instr struct {
- Pageload string `json:"pageload"`
- Dssostatus string `json:"dssostatus"`
- } `json:"instr"`
- } `json:"urls"`
- Browser struct {
- Ltr int `json:"ltr"`
- Other int `json:"_Other"`
- Full int `json:"Full"`
- REOther int `json:"RE_Other"`
- B struct {
- Name string `json:"name"`
- Major int `json:"major"`
- Minor int `json:"minor"`
- } `json:"b"`
- Os struct {
- Name string `json:"name"`
- Version string `json:"version"`
- } `json:"os"`
- V int `json:"V"`
- } `json:"browser"`
- Watson struct {
- URL string `json:"url"`
- Bundle string `json:"bundle"`
- Sbundle string `json:"sbundle"`
- Fbundle string `json:"fbundle"`
- ResetErrorPeriod int `json:"resetErrorPeriod"`
- MaxCorsErrors int `json:"maxCorsErrors"`
- MaxInjectErrors int `json:"maxInjectErrors"`
- MaxErrors int `json:"maxErrors"`
- MaxTotalErrors int `json:"maxTotalErrors"`
- ExpSrcs []string `json:"expSrcs"`
- EnvErrorRedirect bool `json:"envErrorRedirect"`
- EnvErrorURL string `json:"envErrorUrl"`
- } `json:"watson"`
- Loader struct {
- CdnRoots []string `json:"cdnRoots"`
- } `json:"loader"`
- ServerDetails struct {
- Slc string `json:"slc"`
- Dc string `json:"dc"`
- Ri string `json:"ri"`
- Ver struct {
- V []int `json:"v"`
- } `json:"ver"`
- Rt string `json:"rt"`
- Et int `json:"et"`
- } `json:"serverDetails"`
- Country string `json:"country"`
- FBreakBrandingSigninString bool `json:"fBreakBrandingSigninString"`
- Bsso struct {
- Type string `json:"type"`
- Reason string `json:"reason"`
- } `json:"bsso"`
- URLNoCookies string `json:"urlNoCookies"`
- FTrimChromeBssoURL bool `json:"fTrimChromeBssoUrl"`
+// Autogenrated Converged Response struct
+// for some cases, some fields may not exist
+type ConvergedResponse struct {
+ URLGetCredentialType string `json:"urlGetCredentialType"`
+ ArrUserProofs []userProof `json:"arrUserProofs"`
+ URLSkipMfaRegistration string `json:"urlSkipMfaRegistration"`
+ OPerAuthPollingInterval map[string]float64 `json:"oPerAuthPollingInterval"`
+ URLBeginAuth string `json:"urlBeginAuth"`
+ URLEndAuth string `json:"urlEndAuth"`
+ URLPost string `json:"urlPost"`
+ SErrorCode string `json:"sErrorCode"`
+ SErrTxt string `json:"sErrTxt"`
+ SPOSTUsername string `json:"sPOST_Username"`
+ SFT string `json:"sFT"`
+ SFTName string `json:"sFTName"`
+ SCtx string `json:"sCtx"`
+ Hpgact int `json:"hpgact"`
+ Hpgid int `json:"hpgid"`
+ Pgid string `json:"pgid"`
+ APICanary string `json:"apiCanary"`
+ Canary string `json:"canary"`
+ CorrelationID string `json:"correlationId"`
+ SessionID string `json:"sessionId"`
}
-// Autogenerate password login response
-// some case, some fields is not exists
-type passwordLoginResponse struct {
- ArrUserProofs []userProof `json:"arrUserProofs"`
- FHideIHaveCodeLink bool `json:"fHideIHaveCodeLink"`
- OPerAuthPollingInterval map[string]float64 `json:"oPerAuthPollingInterval"`
- FProofIndexedByType bool `json:"fProofIndexedByType"`
- URLBeginAuth string `json:"urlBeginAuth"`
- URLEndAuth string `json:"urlEndAuth"`
- ISAMode int `json:"iSAMode"`
- ITrustedDeviceCheckboxConfig int `json:"iTrustedDeviceCheckboxConfig"`
- IMaxPollAttempts int `json:"iMaxPollAttempts"`
- IPollingTimeout int `json:"iPollingTimeout"`
- IPollingBackoffInterval float64 `json:"iPollingBackoffInterval"`
- IRememberMfaDuration float64 `json:"iRememberMfaDuration"`
- STrustedDeviceCheckboxName string `json:"sTrustedDeviceCheckboxName"`
- SAuthMethodInputFieldName string `json:"sAuthMethodInputFieldName"`
- ISAOtcLength int `json:"iSAOtcLength"`
- ITotpOtcLength int `json:"iTotpOtcLength"`
- URLMoreInfo string `json:"urlMoreInfo"`
- FShowViewDetailsLink bool `json:"fShowViewDetailsLink"`
- FAlwaysUpdateFTInSasEnd bool `json:"fAlwaysUpdateFTInSasEnd"`
- IMaxStackForKnockoutAsyncComponents int `json:"iMaxStackForKnockoutAsyncComponents"`
- StrCopyrightTxt string `json:"strCopyrightTxt"`
- FShowButtons bool `json:"fShowButtons"`
- URLCdn string `json:"urlCdn"`
- URLFooterTOU string `json:"urlFooterTOU"`
- URLFooterPrivacy string `json:"urlFooterPrivacy"`
- URLPost string `json:"urlPost"`
- URLCancel string `json:"urlCancel"`
- IPawnIcon int `json:"iPawnIcon"`
- IPollingInterval int `json:"iPollingInterval"`
- SPOSTUsername string `json:"sPOST_Username"`
- SFT string `json:"sFT"`
- SFTName string `json:"sFTName"`
- SCtx string `json:"sCtx"`
- DynamicTenantBranding []struct {
- Locale int `json:"Locale"`
- Illustration string `json:"Illustration"`
- UserIDLabel string `json:"UserIdLabel"`
- KeepMeSignedInDisabled bool `json:"KeepMeSignedInDisabled"`
- UseTransparentLightBox bool `json:"UseTransparentLightBox"`
- } `json:"dynamicTenantBranding"`
- OAppCobranding struct {
- } `json:"oAppCobranding"`
- IBackgroundImage int `json:"iBackgroundImage"`
- FUseConstantPolling bool `json:"fUseConstantPolling"`
- FUseFlowTokenAsCanary bool `json:"fUseFlowTokenAsCanary"`
- FApplicationInsightsEnabled bool `json:"fApplicationInsightsEnabled"`
- IApplicationInsightsEnabledPercentage int `json:"iApplicationInsightsEnabledPercentage"`
- URLSetDebugMode string `json:"urlSetDebugMode"`
- FEnableCSSAnimation bool `json:"fEnableCssAnimation"`
- FAllowGrayOutLightBox bool `json:"fAllowGrayOutLightBox"`
- FIsRemoteNGCSupported bool `json:"fIsRemoteNGCSupported"`
- Scid int `json:"scid"`
- Hpgact int `json:"hpgact"`
- Hpgid int `json:"hpgid"`
- Pgid string `json:"pgid"`
- APICanary string `json:"apiCanary"`
- Canary string `json:"canary"`
- CorrelationID string `json:"correlationId"`
- SessionID string `json:"sessionId"`
- Locale struct {
- Mkt string `json:"mkt"`
- Lcid int `json:"lcid"`
- } `json:"locale"`
- SlMaxRetry int `json:"slMaxRetry"`
- SlReportFailure bool `json:"slReportFailure"`
- Strings struct {
- Desktopsso struct {
- Authenticatingmessage string `json:"authenticatingmessage"`
- } `json:"desktopsso"`
- } `json:"strings"`
- Enums struct {
- ClientMetricsModes struct {
- None int `json:"None"`
- SubmitOnPost int `json:"SubmitOnPost"`
- SubmitOnRedirect int `json:"SubmitOnRedirect"`
- InstrumentPlt int `json:"InstrumentPlt"`
- } `json:"ClientMetricsModes"`
- } `json:"enums"`
- Urls struct {
- Instr struct {
- Pageload string `json:"pageload"`
- Dssostatus string `json:"dssostatus"`
- } `json:"instr"`
- } `json:"urls"`
- Browser struct {
- Ltr int `json:"ltr"`
- Other int `json:"_Other"`
- Full int `json:"Full"`
- REOther int `json:"RE_Other"`
- B struct {
- Name string `json:"name"`
- Major int `json:"major"`
- Minor int `json:"minor"`
- } `json:"b"`
- Os struct {
- Name string `json:"name"`
- Version string `json:"version"`
- } `json:"os"`
- V int `json:"V"`
- } `json:"browser"`
- Watson struct {
- URL string `json:"url"`
- Bundle string `json:"bundle"`
- Sbundle string `json:"sbundle"`
- Fbundle string `json:"fbundle"`
- ResetErrorPeriod int `json:"resetErrorPeriod"`
- MaxCorsErrors int `json:"maxCorsErrors"`
- MaxInjectErrors int `json:"maxInjectErrors"`
- MaxErrors int `json:"maxErrors"`
- MaxTotalErrors int `json:"maxTotalErrors"`
- ExpSrcs []string `json:"expSrcs"`
- EnvErrorRedirect bool `json:"envErrorRedirect"`
- EnvErrorURL string `json:"envErrorUrl"`
- } `json:"watson"`
- Loader struct {
- CdnRoots []string `json:"cdnRoots"`
- } `json:"loader"`
- ServerDetails struct {
- Slc string `json:"slc"`
- Dc string `json:"dc"`
- Ri string `json:"ri"`
- Ver struct {
- V []int `json:"v"`
- } `json:"ver"`
- Rt string `json:"rt"`
- Et int `json:"et"`
- } `json:"serverDetails"`
- Country string `json:"country"`
- FBreakBrandingSigninString bool `json:"fBreakBrandingSigninString"`
- URLNoCookies string `json:"urlNoCookies"`
- FTrimChromeBssoURL bool `json:"fTrimChromeBssoUrl"`
+// Autogenerated GetCredentialType Request struct
+// for some cases, some fields may not exist
+type GetCredentialTypeRequest struct {
+ Username string `json:"username"`
+ IsOtherIdpSupported bool `json:"isOtherIdpSupported"`
+ CheckPhones bool `json:"checkPhones"`
+ IsRemoteNGCSupported bool `json:"isRemoteNGCSupported"`
+ IsCookieBannerShown bool `json:"isCookieBannerShown"`
+ IsFidoSupported bool `json:"isFidoSupported"`
+ OriginalRequest string `json:"originalRequest"`
+ Country string `json:"country"`
+ Forceotclogin bool `json:"forceotclogin"`
+ IsExternalFederationDisallowed bool `json:"isExternalFederationDisallowed"`
+ IsRemoteConnectSupported bool `json:"isRemoteConnectSupported"`
+ FederationFlags int `json:"federationFlags"`
+ IsSignup bool `json:"isSignup"`
+ FlowToken string `json:"flowToken"`
+ IsAccessPassSupported bool `json:"isAccessPassSupported"`
}
-// Autogenerated skip mfa login response
-type SkipMfaResponse struct {
- URLPostRedirect string `json:"urlPostRedirect"`
- URLSkipMfaRegistration string `json:"urlSkipMfaRegistration"`
- URLMoreInfo string `json:"urlMoreInfo"`
- SProofUpToken string `json:"sProofUpToken"`
- SProofUpTokenName string `json:"sProofUpTokenName"`
- SProofUpAuthState string `json:"sProofUpAuthState"`
- SCanaryToken string `json:"sCanaryToken"`
- IRemainingDaysToSkipMfaRegistration int `json:"iRemainingDaysToSkipMfaRegistration"`
- IMaxStackForKnockoutAsyncComponents int `json:"iMaxStackForKnockoutAsyncComponents"`
- StrCopyrightTxt string `json:"strCopyrightTxt"`
- FShowButtons bool `json:"fShowButtons"`
- URLCdn string `json:"urlCdn"`
- URLFooterTOU string `json:"urlFooterTOU"`
- URLFooterPrivacy string `json:"urlFooterPrivacy"`
- URLPost string `json:"urlPost"`
- URLCancel string `json:"urlCancel"`
- IPawnIcon int `json:"iPawnIcon"`
- SPOSTUsername string `json:"sPOST_Username"`
- SFT string `json:"sFT"`
- SFTName string `json:"sFTName"`
- SCanaryTokenName string `json:"sCanaryTokenName"`
- DynamicTenantBranding []struct {
- Locale int `json:"Locale"`
- Illustration string `json:"Illustration"`
- UserIDLabel string `json:"UserIdLabel"`
- KeepMeSignedInDisabled bool `json:"KeepMeSignedInDisabled"`
- UseTransparentLightBox bool `json:"UseTransparentLightBox"`
- } `json:"dynamicTenantBranding"`
- OAppCobranding struct {
- } `json:"oAppCobranding"`
- IBackgroundImage int `json:"iBackgroundImage"`
- FUseConstantPolling bool `json:"fUseConstantPolling"`
- FUseFlowTokenAsCanary bool `json:"fUseFlowTokenAsCanary"`
- FApplicationInsightsEnabled bool `json:"fApplicationInsightsEnabled"`
- IApplicationInsightsEnabledPercentage int `json:"iApplicationInsightsEnabledPercentage"`
- URLSetDebugMode string `json:"urlSetDebugMode"`
- FEnableCSSAnimation bool `json:"fEnableCssAnimation"`
- FAllowGrayOutLightBox bool `json:"fAllowGrayOutLightBox"`
- FIsRemoteNGCSupported bool `json:"fIsRemoteNGCSupported"`
- Scid int `json:"scid"`
- Hpgact int `json:"hpgact"`
- Hpgid int `json:"hpgid"`
- Pgid string `json:"pgid"`
- APICanary string `json:"apiCanary"`
- Canary string `json:"canary"`
- CorrelationID string `json:"correlationId"`
- SessionID string `json:"sessionId"`
- Locale struct {
- Mkt string `json:"mkt"`
- Lcid int `json:"lcid"`
- } `json:"locale"`
- SlMaxRetry int `json:"slMaxRetry"`
- SlReportFailure bool `json:"slReportFailure"`
- Strings struct {
- Desktopsso struct {
- Authenticatingmessage string `json:"authenticatingmessage"`
- } `json:"desktopsso"`
- } `json:"strings"`
- Enums struct {
- ClientMetricsModes struct {
- None int `json:"None"`
- SubmitOnPost int `json:"SubmitOnPost"`
- SubmitOnRedirect int `json:"SubmitOnRedirect"`
- InstrumentPlt int `json:"InstrumentPlt"`
- } `json:"ClientMetricsModes"`
- } `json:"enums"`
- Urls struct {
- Instr struct {
- Pageload string `json:"pageload"`
- Dssostatus string `json:"dssostatus"`
- } `json:"instr"`
- } `json:"urls"`
- Browser struct {
- Ltr int `json:"ltr"`
- Other int `json:"_Other"`
- Full int `json:"Full"`
- REOther int `json:"RE_Other"`
- B struct {
- Name string `json:"name"`
- Major int `json:"major"`
- Minor int `json:"minor"`
- } `json:"b"`
- Os struct {
- Name string `json:"name"`
- Version string `json:"version"`
- } `json:"os"`
- V int `json:"V"`
- } `json:"browser"`
- Watson struct {
- URL string `json:"url"`
- Bundle string `json:"bundle"`
- Sbundle string `json:"sbundle"`
- Fbundle string `json:"fbundle"`
- ResetErrorPeriod int `json:"resetErrorPeriod"`
- MaxCorsErrors int `json:"maxCorsErrors"`
- MaxInjectErrors int `json:"maxInjectErrors"`
- MaxErrors int `json:"maxErrors"`
- MaxTotalErrors int `json:"maxTotalErrors"`
- ExpSrcs []string `json:"expSrcs"`
- EnvErrorRedirect bool `json:"envErrorRedirect"`
- EnvErrorURL string `json:"envErrorUrl"`
- } `json:"watson"`
- Loader struct {
- CdnRoots []string `json:"cdnRoots"`
- } `json:"loader"`
- ServerDetails struct {
- Slc string `json:"slc"`
- Dc string `json:"dc"`
- Ri string `json:"ri"`
- Ver struct {
- V []int `json:"v"`
- } `json:"ver"`
- Rt string `json:"rt"`
- Et int `json:"et"`
- } `json:"serverDetails"`
- Country string `json:"country"`
- FBreakBrandingSigninString bool `json:"fBreakBrandingSigninString"`
- URLNoCookies string `json:"urlNoCookies"`
- FTrimChromeBssoURL bool `json:"fTrimChromeBssoUrl"`
+// Autogenerated GetCredentialType Response struct
+// for some cases, some fields may not exist
+type GetCredentialTypeResponse struct {
+ Username string `json:"Username"`
+ Display string `json:"Display"`
+ IfExistsResult int `json:"IfExistsResult"`
+ IsUnmanaged bool `json:"IsUnmanaged"`
+ ThrottleStatus int `json:"ThrottleStatus"`
+ Credentials struct {
+ PrefCredential int `json:"PrefCredential"`
+ HasPassword bool `json:"HasPassword"`
+ RemoteNgcParams interface{} `json:"RemoteNgcParams"`
+ FidoParams interface{} `json:"FidoParams"`
+ SasParams interface{} `json:"SasParams"`
+ CertAuthParams interface{} `json:"CertAuthParams"`
+ GoogleParams interface{} `json:"GoogleParams"`
+ FacebookParams interface{} `json:"FacebookParams"`
+ FederationRedirectURL string `json:"FederationRedirectUrl"`
+ } `json:"Credentials"`
+ FlowToken string `json:"FlowToken"`
+ IsSignupDisallowed bool `json:"IsSignupDisallowed"`
+ APICanary string `json:"apiCanary"`
}
-// mfa request
+// MFA Request struct
type mfaRequest struct {
AuthMethodID string `json:"AuthMethodId"`
Method string `json:"Method"`
@@ -473,7 +111,7 @@ type mfaRequest struct {
AdditionalAuthData string `json:"AdditionalAuthData,omitempty"`
}
-// mfa response
+// MFA Response struct
type mfaResponse struct {
Success bool `json:"Success"`
ResultValue string `json:"ResultValue"`
@@ -486,122 +124,7 @@ type mfaResponse struct {
SessionID string `json:"SessionId"`
CorrelationID string `json:"CorrelationId"`
Timestamp time.Time `json:"Timestamp"`
-}
-
-// Autogenerate ProcessAuth response
-// some case, some fields is not exists
-type processAuthResponse struct {
- IMaxStackForKnockoutAsyncComponents int `json:"iMaxStackForKnockoutAsyncComponents"`
- StrCopyrightTxt string `json:"strCopyrightTxt"`
- FShowButtons bool `json:"fShowButtons"`
- URLCdn string `json:"urlCdn"`
- URLFooterTOU string `json:"urlFooterTOU"`
- URLFooterPrivacy string `json:"urlFooterPrivacy"`
- URLPost string `json:"urlPost"`
- IPawnIcon int `json:"iPawnIcon"`
- SPOSTUsername string `json:"sPOST_Username"`
- SFT string `json:"sFT"`
- SFTName string `json:"sFTName"`
- SCtx string `json:"sCtx"`
- SCanaryTokenName string `json:"sCanaryTokenName"`
- DynamicTenantBranding []struct {
- Locale int `json:"Locale"`
- Illustration string `json:"Illustration"`
- UserIDLabel string `json:"UserIdLabel"`
- KeepMeSignedInDisabled bool `json:"KeepMeSignedInDisabled"`
- UseTransparentLightBox bool `json:"UseTransparentLightBox"`
- } `json:"dynamicTenantBranding"`
- OAppCobranding struct {
- } `json:"oAppCobranding"`
- IBackgroundImage int `json:"iBackgroundImage"`
- FUseConstantPolling bool `json:"fUseConstantPolling"`
- FUseFlowTokenAsCanary bool `json:"fUseFlowTokenAsCanary"`
- FApplicationInsightsEnabled bool `json:"fApplicationInsightsEnabled"`
- IApplicationInsightsEnabledPercentage int `json:"iApplicationInsightsEnabledPercentage"`
- URLSetDebugMode string `json:"urlSetDebugMode"`
- FEnableCSSAnimation bool `json:"fEnableCssAnimation"`
- FAllowGrayOutLightBox bool `json:"fAllowGrayOutLightBox"`
- FIsRemoteNGCSupported bool `json:"fIsRemoteNGCSupported"`
- Scid int `json:"scid"`
- Hpgact int `json:"hpgact"`
- Hpgid int `json:"hpgid"`
- Pgid string `json:"pgid"`
- APICanary string `json:"apiCanary"`
- Canary string `json:"canary"`
- CorrelationID string `json:"correlationId"`
- SessionID string `json:"sessionId"`
- Locale struct {
- Mkt string `json:"mkt"`
- Lcid int `json:"lcid"`
- } `json:"locale"`
- SlMaxRetry int `json:"slMaxRetry"`
- SlReportFailure bool `json:"slReportFailure"`
- Strings struct {
- Desktopsso struct {
- Authenticatingmessage string `json:"authenticatingmessage"`
- } `json:"desktopsso"`
- } `json:"strings"`
- Enums struct {
- ClientMetricsModes struct {
- None int `json:"None"`
- SubmitOnPost int `json:"SubmitOnPost"`
- SubmitOnRedirect int `json:"SubmitOnRedirect"`
- InstrumentPlt int `json:"InstrumentPlt"`
- } `json:"ClientMetricsModes"`
- } `json:"enums"`
- Urls struct {
- Instr struct {
- Pageload string `json:"pageload"`
- Dssostatus string `json:"dssostatus"`
- } `json:"instr"`
- } `json:"urls"`
- Browser struct {
- Ltr int `json:"ltr"`
- Other int `json:"_Other"`
- Full int `json:"Full"`
- REOther int `json:"RE_Other"`
- B struct {
- Name string `json:"name"`
- Major int `json:"major"`
- Minor int `json:"minor"`
- } `json:"b"`
- Os struct {
- Name string `json:"name"`
- Version string `json:"version"`
- } `json:"os"`
- V int `json:"V"`
- } `json:"browser"`
- Watson struct {
- URL string `json:"url"`
- Bundle string `json:"bundle"`
- Sbundle string `json:"sbundle"`
- Fbundle string `json:"fbundle"`
- ResetErrorPeriod int `json:"resetErrorPeriod"`
- MaxCorsErrors int `json:"maxCorsErrors"`
- MaxInjectErrors int `json:"maxInjectErrors"`
- MaxErrors int `json:"maxErrors"`
- MaxTotalErrors int `json:"maxTotalErrors"`
- ExpSrcs []string `json:"expSrcs"`
- EnvErrorRedirect bool `json:"envErrorRedirect"`
- EnvErrorURL string `json:"envErrorUrl"`
- } `json:"watson"`
- Loader struct {
- CdnRoots []string `json:"cdnRoots"`
- } `json:"loader"`
- ServerDetails struct {
- Slc string `json:"slc"`
- Dc string `json:"dc"`
- Ri string `json:"ri"`
- Ver struct {
- V []int `json:"v"`
- } `json:"ver"`
- Rt string `json:"rt"`
- Et int `json:"et"`
- } `json:"serverDetails"`
- Country string `json:"country"`
- FBreakBrandingSigninString bool `json:"fBreakBrandingSigninString"`
- URLNoCookies string `json:"urlNoCookies"`
- FTrimChromeBssoURL bool `json:"fTrimChromeBssoUrl"`
+ Entropy int `json:"Entropy"`
}
// A given method for a user to prove their indentity
@@ -633,337 +156,299 @@ func New(idpAccount *cfg.IDPAccount) (*Client, error) {
// Authenticate to AzureAD and return the data from the body of the SAML assertion.
func (ac *Client) Authenticate(loginDetails *creds.LoginDetails) (string, error) {
-
var samlAssertion string
var res *http.Response
+ var err error
+ var resBody []byte
+ var resBodyStr string
+ var convergedResponse *ConvergedResponse
// idpAccount.URL = https://account.activedirectory.windowsazure.com
// startSAML
startURL := fmt.Sprintf("%s/applications/redirecttofederatedapplication.aspx?Operation=LinkedSignIn&applicationId=%s", ac.idpAccount.URL, ac.idpAccount.AppID)
- res, err := ac.client.Get(startURL)
+ res, err = ac.client.Get(startURL)
if err != nil {
- return samlAssertion, errors.Wrap(err, "error retrieving form")
+ return samlAssertion, errors.Wrap(err, "error retrieving entry URL")
+ }
+
+AuthProcessor:
+ for {
+ resBody, _ = io.ReadAll(res.Body)
+ resBodyStr = string(resBody)
+ // reset res.Body so it can be read again later if required
+ res.Body = io.NopCloser(bytes.NewBuffer(resBody))
+
+ switch {
+ case strings.Contains(resBodyStr, "ConvergedSignIn"):
+ logger.Debug("processing ConvergedSignIn")
+ res, err = ac.processConvergedSignIn(res, resBodyStr, loginDetails)
+ case strings.Contains(resBodyStr, "ConvergedProofUpRedirect"):
+ logger.Debug("processing ConvergedProofUpRedirect")
+ res, err = ac.processConvergedProofUpRedirect(res, resBodyStr)
+ case strings.Contains(resBodyStr, "KmsiInterrupt"):
+ logger.Debug("processing KmsiInterrupt")
+ res, err = ac.processKmsiInterrupt(res, resBodyStr)
+ case strings.Contains(resBodyStr, "ConvergedTFA"):
+ logger.Debug("processing ConvergedTFA")
+ res, err = ac.processConvergedTFA(res, resBodyStr)
+ case strings.Contains(resBodyStr, "SAMLRequest"):
+ logger.Debug("processing SAMLRequest")
+ res, err = ac.processSAMLRequest(res, resBodyStr)
+ case ac.isHiddenForm(resBodyStr):
+ if samlAssertion, _ = ac.getSamlAssertion(resBodyStr); samlAssertion != "" {
+ logger.Debug("processing a SAMLResponse")
+ return samlAssertion, nil
+ }
+ logger.Debug("processing a 'hiddenform'")
+ res, err = ac.reProcessForm(resBodyStr)
+ default:
+ if strings.Contains(resBodyStr, "$Config") {
+ if err := ac.unmarshalEmbeddedJson(resBodyStr, &convergedResponse); err != nil {
+ return samlAssertion, errors.Wrap(err, "unmarshal error")
+ }
+ logger.Debug("unknown process step found:", convergedResponse.Pgid)
+ } else {
+ logger.Debug("reached an unknown page within the authentication process")
+ }
+ break AuthProcessor
+ }
+ if err != nil {
+ return samlAssertion, err
+ }
}
- // data is embedded javascript object
- //