|
39 | 39 |
|
40 | 40 | noqa: D103
|
41 | 41 | """
|
| 42 | +import getpass |
42 | 43 | import json
|
43 | 44 | import os
|
44 | 45 | import shutil
|
|
48 | 49 | import click
|
49 | 50 |
|
50 | 51 | from eodag.api.core import DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE, EODataAccessGateway
|
| 52 | +from eodag.config import ( |
| 53 | + get_provider_credentials, |
| 54 | + save_providers_credentials, |
| 55 | + set_provider_credentials_key, |
| 56 | +) |
51 | 57 | from eodag.utils import parse_qs
|
| 58 | +from eodag.utils.cli import ask_confirmation |
52 | 59 | from eodag.utils.exceptions import NoMatchingProductType, UnsupportedProvider
|
53 | 60 | from eodag.utils.logging import setup_logging
|
| 61 | +from eodag.utils.security import Crypto |
54 | 62 |
|
55 | 63 | # A list of supported crunchers that the user can choose (see --cruncher option below)
|
56 | 64 | CRUNCHERS = [
|
@@ -830,5 +838,199 @@ def deploy_wsgi_app(
|
830 | 838 | click.echo(apache_config_sample)
|
831 | 839 |
|
832 | 840 |
|
| 841 | +@eodag.command( |
| 842 | + name="credentials", |
| 843 | + help="This command can be used to create, read, update, or delete a provider's credentials. " |
| 844 | + "Default behavior is create/update.", |
| 845 | +) |
| 846 | +@click.option( |
| 847 | + "-f", |
| 848 | + "--conf", |
| 849 | + type=click.Path(exists=True), |
| 850 | + help="File path to the user configuration file, default is ~/.config/eodag/eodag.yml", |
| 851 | +) |
| 852 | +@click.option( |
| 853 | + "-c", |
| 854 | + "--creds", |
| 855 | + type=click.Path(exists=False), |
| 856 | + help="File path to the credentials file, default is ~/.config/eodag/credentials", |
| 857 | +) |
| 858 | +@click.option( |
| 859 | + "-y", |
| 860 | + "--yes", |
| 861 | + is_flag=True, |
| 862 | + help="Answers yes to command confirmation, disabling safety of credentials update, read and deletion", |
| 863 | +) |
| 864 | +@click.option( |
| 865 | + "-l", |
| 866 | + "--list", |
| 867 | + is_flag=True, |
| 868 | + help="Display the provider's credentials fields names", |
| 869 | +) |
| 870 | +@click.option( |
| 871 | + "-e", |
| 872 | + "--exists", |
| 873 | + is_flag=True, |
| 874 | + help="Check if the provider's credentials exists in the credentials file. " |
| 875 | + "WARNING: Raw credentials in the user conf are not checked", |
| 876 | +) |
| 877 | +@click.option( |
| 878 | + "-s", |
| 879 | + "--set", |
| 880 | + multiple=True, |
| 881 | + help="Set a provider's credentials value", |
| 882 | +) |
| 883 | +@click.option( |
| 884 | + "-r", |
| 885 | + "--read", |
| 886 | + is_flag=True, |
| 887 | + help="Read the provider's credentials and display them. WARNING: " |
| 888 | + "This command may display sensible informations, be wary of it", |
| 889 | +) |
| 890 | +@click.option( |
| 891 | + "-d", |
| 892 | + "--delete", |
| 893 | + is_flag=True, |
| 894 | + help="Delete the provider's credentials", |
| 895 | +) |
| 896 | +@click.argument("provider", type=str) |
| 897 | +@click.pass_context |
| 898 | +def credentials(ctx, **kwargs): |
| 899 | + """Command used to create, read, update, or delete a provider's credentials, Default behavior is create/update.""" |
| 900 | + setup_logging(verbose=ctx.obj["verbosity"]) |
| 901 | + |
| 902 | + conf_file = kwargs.pop("conf") |
| 903 | + if conf_file: |
| 904 | + conf_file = click.format_filename(conf_file) |
| 905 | + creds_file = kwargs.pop("creds") |
| 906 | + if creds_file: |
| 907 | + creds_file = click.format_filename(creds_file) |
| 908 | + |
| 909 | + dag = EODataAccessGateway( |
| 910 | + user_conf_file_path=conf_file, credentials_file_path=creds_file |
| 911 | + ) |
| 912 | + providers = dag.available_providers() |
| 913 | + provider = kwargs.pop("provider") |
| 914 | + |
| 915 | + if provider not in providers: |
| 916 | + click.echo( |
| 917 | + f"Error: Provider '{provider}' not found in available providers.", |
| 918 | + err=True, |
| 919 | + ) |
| 920 | + sys.exit(-1) |
| 921 | + |
| 922 | + provider_credentials = get_provider_credentials(dag.providers_config[provider]) |
| 923 | + encrypted_credentials = {**dag.encrypted_credentials} |
| 924 | + provider_has_encrypted_credentials = provider in dag.encrypted_credentials |
| 925 | + |
| 926 | + do_list = kwargs.pop("list") |
| 927 | + if do_list: |
| 928 | + creds_names = list(provider_credentials.keys()) |
| 929 | + click.echo( |
| 930 | + f"Credentials field{'s' if len(creds_names)>1 else ''} for '{provider}': ", |
| 931 | + nl=False, |
| 932 | + ) |
| 933 | + click.echo(", ".join(creds_names)) |
| 934 | + sys.exit(0) |
| 935 | + |
| 936 | + do_exists = kwargs.pop("exists") |
| 937 | + if do_exists: |
| 938 | + if provider_has_encrypted_credentials: |
| 939 | + click.echo(f"Credentials found for provider '{provider}'.") |
| 940 | + sys.exit(0) |
| 941 | + else: |
| 942 | + click.echo( |
| 943 | + f"Error: No credentials found for the provider '{provider}' inside '{dag.credentials_file_path}'.", |
| 944 | + err=True, |
| 945 | + ) |
| 946 | + sys.exit(-1) |
| 947 | + |
| 948 | + confirm_yes = kwargs.pop("yes") |
| 949 | + |
| 950 | + do_read = kwargs.pop("read") |
| 951 | + if do_read: |
| 952 | + if provider in dag.encrypted_credentials: |
| 953 | + if not confirm_yes: |
| 954 | + confirm = ask_confirmation( |
| 955 | + f"Do you want to read the credentials saved for '{provider}' " |
| 956 | + f"inside '{dag.credentials_file_path}'?" |
| 957 | + ) |
| 958 | + if not confirm: |
| 959 | + sys.exit(1) |
| 960 | + for cred_name, cred in provider_credentials.items(): |
| 961 | + click.echo(f"{cred_name}: {cred}") |
| 962 | + sys.exit(0) |
| 963 | + else: |
| 964 | + click.echo( |
| 965 | + f"Error: No credentials found for the provider '{provider}' " |
| 966 | + f"inside '{dag.credentials_file_path}', cannot read." |
| 967 | + "", |
| 968 | + err=True, |
| 969 | + ) |
| 970 | + sys.exit(-1) |
| 971 | + |
| 972 | + do_delete = kwargs.pop("delete") |
| 973 | + if do_delete: |
| 974 | + if provider in dag.encrypted_credentials: |
| 975 | + if not confirm_yes: |
| 976 | + confirm = ask_confirmation( |
| 977 | + f"Do you want to delete the credentials saved for '{provider}' " |
| 978 | + f"inside '{dag.credentials_file_path}'?" |
| 979 | + ) |
| 980 | + if not confirm: |
| 981 | + sys.exit(1) |
| 982 | + del encrypted_credentials[provider] |
| 983 | + save_providers_credentials(dag.credentials_file_path, encrypted_credentials) |
| 984 | + click.echo(f"Credentials of '{provider}' were deleted.") |
| 985 | + sys.exit(0) |
| 986 | + else: |
| 987 | + click.echo( |
| 988 | + f"Error: No credentials found for the provider '{provider}' " |
| 989 | + f"inside '{dag.credentials_file_path}', cannot delete.", |
| 990 | + err=True, |
| 991 | + ) |
| 992 | + sys.exit(-1) |
| 993 | + |
| 994 | + if provider in dag.encrypted_credentials and not confirm_yes: |
| 995 | + confirm = ask_confirmation( |
| 996 | + f"The provider '{provider}' already have credentials saved inside '{dag.credentials_file_path}', " |
| 997 | + "do you want to override them?" |
| 998 | + ) |
| 999 | + if not confirm: |
| 1000 | + sys.exit(1) |
| 1001 | + |
| 1002 | + crypto = Crypto() |
| 1003 | + new_creds = {} |
| 1004 | + |
| 1005 | + creds_from_cli = kwargs.pop("set") |
| 1006 | + if creds_from_cli: |
| 1007 | + for cred_def in creds_from_cli: |
| 1008 | + cred_name, *cred_parts = str(cred_def).split("=", 1) |
| 1009 | + cred = "".join(cred_parts) |
| 1010 | + if cred and cred_name in provider_credentials: |
| 1011 | + new_creds[cred_name] = crypto.encrypt(cred) |
| 1012 | + |
| 1013 | + remaining = list(filter(lambda i: i not in new_creds, provider_credentials)) |
| 1014 | + if remaining: |
| 1015 | + click.echo( |
| 1016 | + f"Error: Missing credentials field{'s' if len(remaining)>1 else ''}: {', '.join(remaining)}.", |
| 1017 | + err=True, |
| 1018 | + ) |
| 1019 | + sys.exit(-1) |
| 1020 | + else: |
| 1021 | + click.echo(f"Enter your credentials for the provider '{provider}':") |
| 1022 | + for cred_name in provider_credentials: |
| 1023 | + cred_input = getpass.getpass(prompt=f"- {cred_name}: ") |
| 1024 | + new_creds[cred_name] = crypto.encrypt(cred_input) |
| 1025 | + |
| 1026 | + set_provider_credentials_key(new_creds, crypto.key) |
| 1027 | + encrypted_credentials[provider] = new_creds |
| 1028 | + |
| 1029 | + save_providers_credentials(dag.credentials_file_path, encrypted_credentials) |
| 1030 | + click.echo( |
| 1031 | + f"Credentials for '{provider}' saved inside '{dag.credentials_file_path}'." |
| 1032 | + ) |
| 1033 | + |
| 1034 | + |
833 | 1035 | if __name__ == "__main__":
|
834 | 1036 | eodag(obj={})
|
0 commit comments