Apply Spring Boot code formatting.
Reformat all code with Spring Boot formatting rules to stay in sync with Spring Cloud Vault. Fixes gh-16.
This commit is contained in:
@@ -1,291 +1,296 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="12">
|
||||
<profile kind="CodeFormatterProfile" name="Spring Data" version="12">
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<profile kind="CodeFormatterProfile" name="Spring Boot Java Conventions" version="12">
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="90"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="90"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
</profiles>
|
||||
7
etc/ide/eclipse.importorder
Normal file
7
etc/ide/eclipse.importorder
Normal file
@@ -0,0 +1,7 @@
|
||||
#Organize Import Order
|
||||
#Thu Oct 13 16:40:43 CEST 2016
|
||||
4=\#
|
||||
3=org.springframework
|
||||
2=
|
||||
1=javax
|
||||
0=java
|
||||
@@ -26,41 +26,47 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Annotation providing a convenient and declarative mechanism for adding a {@link VaultPropertySource} to Spring's
|
||||
* {@link org.springframework.core.env.Environment Environment}. To be used in conjunction with @{@link Configuration}
|
||||
* classes.
|
||||
* <h3>Example usage</h3>
|
||||
* Annotation providing a convenient and declarative mechanism for adding a
|
||||
* {@link VaultPropertySource} to Spring's
|
||||
* {@link org.springframework.core.env.Environment Environment}. To be used in conjunction
|
||||
* with @{@link Configuration} classes. <h3>Example usage</h3>
|
||||
* <p>
|
||||
* Given a Vault path {@code secret/my-application} containing the configuration data pair
|
||||
* {@code database.password=mysecretpassword}, the following {@code @Configuration} class uses
|
||||
* {@code @VaultPropertySource} to contribute {@code secret/my-application} to the {@code Environment}'s set of
|
||||
* {@code PropertySources}.
|
||||
* {@code database.password=mysecretpassword}, the following {@code @Configuration} class
|
||||
* uses {@code @VaultPropertySource} to contribute {@code secret/my-application} to the
|
||||
* {@code Environment}'s set of {@code PropertySources}.
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* @VaultPropertySource("secret/my-application")
|
||||
* @VaultPropertySource("secret/my-application")
|
||||
* public class AppConfig {
|
||||
* @Autowired Environment env;
|
||||
*
|
||||
* @Autowired
|
||||
* Environment env;
|
||||
*
|
||||
* @Bean
|
||||
* public TestBean testBean() {
|
||||
* TestBean testBean = new TestBean();
|
||||
* testBean.setPassword(env.getProperty("database.password"));
|
||||
* testBean.setPassword(env.getProperty("database.password"));
|
||||
* return testBean;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Notice that the {@code Environment} object is @{@link org.springframework.beans.factory.annotation.Autowired
|
||||
* Autowired} into the configuration class and then used when populating the {@code TestBean} object. Given the
|
||||
* configuration above, a call to {@code testBean.getPassword()} will return "mysecretpassword".
|
||||
* Notice that the {@code Environment} object is @
|
||||
* {@link org.springframework.beans.factory.annotation.Autowired Autowired} into the
|
||||
* configuration class and then used when populating the {@code TestBean} object. Given
|
||||
* the configuration above, a call to {@code testBean.getPassword()} will return
|
||||
* "mysecretpassword".
|
||||
* <p>
|
||||
* In certain situations, it may not be possible or practical to tightly control property source ordering when using
|
||||
* {@code @VaultPropertySource} annotations. For example, if the {@code @Configuration} classes above were registered
|
||||
* via component-scanning, the ordering is difficult to predict. In such cases - and if overriding is important - it is
|
||||
* recommended that the user fall back to using the programmatic PropertySource API. See
|
||||
* {@link org.springframework.core.env.ConfigurableEnvironment ConfigurableEnvironment} and
|
||||
* {@link org.springframework.core.env.MutablePropertySources MutablePropertySources} javadocs for details.
|
||||
* In certain situations, it may not be possible or practical to tightly control property
|
||||
* source ordering when using {@code @VaultPropertySource} annotations. For example, if
|
||||
* the {@code @Configuration} classes above were registered via component-scanning, the
|
||||
* ordering is difficult to predict. In such cases - and if overriding is important - it
|
||||
* is recommended that the user fall back to using the programmatic PropertySource API.
|
||||
* See {@link org.springframework.core.env.ConfigurableEnvironment
|
||||
* ConfigurableEnvironment} and
|
||||
* {@link org.springframework.core.env.MutablePropertySources MutablePropertySources}
|
||||
* javadocs for details.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -72,17 +78,17 @@ import org.springframework.context.annotation.Import;
|
||||
public @interface VaultPropertySource {
|
||||
|
||||
/**
|
||||
* Indicate the Vault path(s) of the properties to be retrieved. For example, {@code "secret/myapp"} or
|
||||
* {@code "secret/my-application/profile"}.
|
||||
* Indicate the Vault path(s) of the properties to be retrieved. For example,
|
||||
* {@code "secret/myapp"} or {@code "secret/my-application/profile"}.
|
||||
* <p>
|
||||
* Each location will be added to the enclosing {@code Environment} as its own property source, and in the order
|
||||
* declared.
|
||||
* Each location will be added to the enclosing {@code Environment} as its own
|
||||
* property source, and in the order declared.
|
||||
*/
|
||||
String[] value();
|
||||
|
||||
/**
|
||||
* Configure the name of the {@link org.springframework.vault.core.VaultTemplate} bean to be used with the property
|
||||
* sources.
|
||||
* Configure the name of the {@link org.springframework.vault.core.VaultTemplate} bean
|
||||
* to be used with the property sources.
|
||||
*/
|
||||
String vaultTemplateRef() default "vaultTemplate";
|
||||
}
|
||||
|
||||
@@ -35,20 +35,23 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Registrar to register {@link org.springframework.vault.core.env.VaultPropertySource}s based on
|
||||
* {@link VaultPropertySource}.
|
||||
* Registrar to register {@link org.springframework.vault.core.env.VaultPropertySource}s
|
||||
* based on {@link VaultPropertySource}.
|
||||
* <p>
|
||||
* This class registers potentially multiple property sources based on different Vault paths.
|
||||
* {@link org.springframework.vault.core.env.VaultPropertySource}s are resolved and added to
|
||||
* {@link ConfigurableEnvironment} once the bean factory is post-processed. This allows injection of Vault properties
|
||||
* and and lookup using the {@link org.springframework.core.env.Environment}.
|
||||
* This class registers potentially multiple property sources based on different Vault
|
||||
* paths. {@link org.springframework.vault.core.env.VaultPropertySource}s are resolved and
|
||||
* added to {@link ConfigurableEnvironment} once the bean factory is post-processed. This
|
||||
* allows injection of Vault properties and and lookup using the
|
||||
* {@link org.springframework.core.env.Environment}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryPostProcessor {
|
||||
class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
BeanFactoryPostProcessor {
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
|
||||
ConfigurableEnvironment env = beanFactory.getBean(ConfigurableEnvironment.class);
|
||||
Map<String, org.springframework.vault.core.env.VaultPropertySource> beans = beanFactory
|
||||
@@ -56,7 +59,8 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar, Bea
|
||||
|
||||
MutablePropertySources propertySources = env.getPropertySources();
|
||||
|
||||
for (org.springframework.vault.core.env.VaultPropertySource vaultPropertySource : beans.values()) {
|
||||
for (org.springframework.vault.core.env.VaultPropertySource vaultPropertySource : beans
|
||||
.values()) {
|
||||
|
||||
if (propertySources.contains(vaultPropertySource.getName())) {
|
||||
continue;
|
||||
@@ -67,7 +71,8 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar, Bea
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
|
||||
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null!");
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
|
||||
@@ -78,19 +83,22 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar, Bea
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE) //
|
||||
.getBeanDefinition());
|
||||
|
||||
Set<AnnotationAttributes> propertySources = attributesForRepeatable(annotationMetadata,
|
||||
VaultPropertySources.class.getName(), VaultPropertySource.class.getName());
|
||||
Set<AnnotationAttributes> propertySources = attributesForRepeatable(
|
||||
annotationMetadata, VaultPropertySources.class.getName(),
|
||||
VaultPropertySource.class.getName());
|
||||
|
||||
int counter = 0;
|
||||
|
||||
for (AnnotationAttributes propertySource : propertySources) {
|
||||
|
||||
String[] paths = propertySource.getStringArray("value");
|
||||
Assert.isTrue(paths.length > 0, "At least one @VaultPropertySource(value) location is required");
|
||||
Assert.isTrue(paths.length > 0,
|
||||
"At least one @VaultPropertySource(value) location is required");
|
||||
|
||||
String ref = propertySource.getString("vaultTemplateRef");
|
||||
|
||||
Assert.hasText(ref, "'vaultTemplateRef' in @EnableVaultPropertySource must not be empty");
|
||||
Assert.hasText(ref,
|
||||
"'vaultTemplateRef' in @EnableVaultPropertySource must not be empty");
|
||||
|
||||
for (String propertyPath : paths) {
|
||||
|
||||
@@ -106,7 +114,8 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar, Bea
|
||||
builder.addConstructorArgValue(propertyPath);
|
||||
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
registry.registerBeanDefinition("vaultPropertySource#" + counter, builder.getBeanDefinition());
|
||||
registry.registerBeanDefinition("vaultPropertySource#" + counter,
|
||||
builder.getBeanDefinition());
|
||||
|
||||
counter++;
|
||||
}
|
||||
@@ -114,22 +123,26 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar, Bea
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata, String containerClassName,
|
||||
String annotationClassName) {
|
||||
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
|
||||
String containerClassName, String annotationClassName) {
|
||||
|
||||
Set<AnnotationAttributes> result = new LinkedHashSet<AnnotationAttributes>();
|
||||
addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
|
||||
addAttributesIfNotNull(result,
|
||||
metadata.getAnnotationAttributes(annotationClassName, false));
|
||||
|
||||
Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
|
||||
Map<String, Object> container = metadata.getAnnotationAttributes(
|
||||
containerClassName, false);
|
||||
if (container != null && container.containsKey("value")) {
|
||||
for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) {
|
||||
for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container
|
||||
.get("value")) {
|
||||
addAttributesIfNotNull(result, containedAttributes);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
|
||||
private static void addAttributesIfNotNull(Set<AnnotationAttributes> result, Map<String, Object> attributes) {
|
||||
private static void addAttributesIfNotNull(Set<AnnotationAttributes> result,
|
||||
Map<String, Object> attributes) {
|
||||
if (attributes != null) {
|
||||
result.add(AnnotationAttributes.fromMap(attributes));
|
||||
}
|
||||
|
||||
@@ -26,10 +26,11 @@ import org.springframework.context.annotation.Import;
|
||||
/**
|
||||
* Container annotation that aggregates several {@link VaultPropertySource} annotations.
|
||||
* <p>
|
||||
* Can be used natively, declaring several nested {@link VaultPropertySource} annotations. Can also be used in
|
||||
* conjunction with Java 8's support for <em>repeatable annotations</em>, where {@link VaultPropertySource} can simply
|
||||
* be declared several times on the same {@linkplain ElementType#TYPE type}, implicitly generating this container
|
||||
* annotation.
|
||||
* Can be used natively, declaring several nested {@link VaultPropertySource} annotations.
|
||||
* Can also be used in conjunction with Java 8's support for
|
||||
* <em>repeatable annotations</em>, where {@link VaultPropertySource} can simply be
|
||||
* declared several times on the same {@linkplain ElementType#TYPE type}, implicitly
|
||||
* generating this container annotation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see VaultPropertySource
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
* Annotation support for the Spring Vault.
|
||||
*/
|
||||
package org.springframework.vault.annotation;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
@@ -28,25 +29,28 @@ import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* AppId implementation of {@link ClientAuthentication}. {@link AppIdAuthentication} uses a configured
|
||||
* {@link AppIdUserIdMechanism} to obtain or calculate a UserId. AppId and UserId are sent in the login request to Vault
|
||||
* to obtain a {@link VaultToken}.
|
||||
* AppId implementation of {@link ClientAuthentication}. {@link AppIdAuthentication} uses
|
||||
* a configured {@link AppIdUserIdMechanism} to obtain or calculate a UserId. AppId and
|
||||
* UserId are sent in the login request to Vault to obtain a {@link VaultToken}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdAuthenticationOptions
|
||||
* @see VaultClient
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/app-id.html">Auth Backend: App ID</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/app-id.html">Auth Backend: App
|
||||
* ID</a>
|
||||
*/
|
||||
public class AppIdAuthentication implements ClientAuthentication {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AppIdAuthentication.class);
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(AppIdAuthentication.class);
|
||||
|
||||
private final AppIdAuthenticationOptions options;
|
||||
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
/**
|
||||
* Creates a {@link AppIdAuthentication} using {@link AppIdAuthenticationOptions} and {@link VaultClient}.
|
||||
* Creates a {@link AppIdAuthentication} using {@link AppIdAuthenticationOptions} and
|
||||
* {@link VaultClient}.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
@@ -67,13 +71,16 @@ public class AppIdAuthentication implements ClientAuthentication {
|
||||
|
||||
private VaultToken createTokenUsingAppId() {
|
||||
|
||||
Map<String, String> login = getAppIdLogin(options.getAppId(), options.getUserIdMechanism().createUserId());
|
||||
Map<String, String> login = getAppIdLogin(options.getAppId(), options
|
||||
.getUserIdMechanism().createUserId());
|
||||
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient
|
||||
.postForEntity(String.format("auth/%s/login", options.getPath()), login, VaultResponse.class);
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient.postForEntity(
|
||||
String.format("auth/%s/login", options.getPath()), login,
|
||||
VaultResponse.class);
|
||||
|
||||
if (!entity.isSuccessful()) {
|
||||
throw new VaultException(String.format("Cannot login using app-id: %s", entity.getMessage()));
|
||||
throw new VaultException(String.format("Cannot login using app-id: %s",
|
||||
entity.getMessage()));
|
||||
}
|
||||
|
||||
logger.debug("Login successful using AppId authentication");
|
||||
|
||||
@@ -20,8 +20,9 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* Authentication options for {@link AppIdAuthentication}.
|
||||
* <p>
|
||||
* Authentication options provide the path, appId and a {@link AppIdUserIdMechanism}. {@link AppIdAuthentication} can be
|
||||
* constructed using {@link #builder()}. Instances of this class are immutable once constructed.
|
||||
* Authentication options provide the path, appId and a {@link AppIdUserIdMechanism}.
|
||||
* {@link AppIdAuthentication} can be constructed using {@link #builder()}. Instances of
|
||||
* this class are immutable once constructed.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdAuthentication
|
||||
@@ -47,7 +48,8 @@ public class AppIdAuthenticationOptions {
|
||||
*/
|
||||
private final AppIdUserIdMechanism userIdMechanism;
|
||||
|
||||
private AppIdAuthenticationOptions(String path, String appId, AppIdUserIdMechanism userIdMechanism) {
|
||||
private AppIdAuthenticationOptions(String path, String appId,
|
||||
AppIdUserIdMechanism userIdMechanism) {
|
||||
|
||||
this.path = path;
|
||||
this.appId = appId;
|
||||
@@ -93,7 +95,8 @@ public class AppIdAuthenticationOptions {
|
||||
|
||||
private AppIdUserIdMechanism userIdMechanism;
|
||||
|
||||
AppIdAuthenticationOptionsBuilder() {}
|
||||
AppIdAuthenticationOptionsBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the mount path.
|
||||
@@ -130,7 +133,8 @@ public class AppIdAuthenticationOptions {
|
||||
* @param userIdMechanism must not be {@literal null}.
|
||||
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
|
||||
*/
|
||||
public AppIdAuthenticationOptionsBuilder userIdMechanism(AppIdUserIdMechanism userIdMechanism) {
|
||||
public AppIdAuthenticationOptionsBuilder userIdMechanism(
|
||||
AppIdUserIdMechanism userIdMechanism) {
|
||||
|
||||
Assert.notNull(userIdMechanism, "AppIdUserIdMechanism must not be null");
|
||||
|
||||
@@ -139,8 +143,8 @@ public class AppIdAuthenticationOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link AppIdAuthenticationOptions} instance. Requires {@link #userIdMechanism(AppIdUserIdMechanism)}
|
||||
* to be configured.
|
||||
* Build a new {@link AppIdAuthenticationOptions} instance. Requires
|
||||
* {@link #userIdMechanism(AppIdUserIdMechanism)} to be configured.
|
||||
*
|
||||
* @return a new {@link AppIdAuthenticationOptions}.
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
/**
|
||||
* Interface to obtain a UserId for AppId authentication. Implementations are used by {@link AppIdAuthentication}.
|
||||
* Interface to obtain a UserId for AppId authentication. Implementations are used by
|
||||
* {@link AppIdAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdAuthentication
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
@@ -28,8 +29,8 @@ import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* AppRole implementation of {@link ClientAuthentication}. RoleId and SecretId (optional) are sent in the login request
|
||||
* to Vault to obtain a {@link VaultToken}.
|
||||
* AppRole implementation of {@link ClientAuthentication}. RoleId and SecretId (optional)
|
||||
* are sent in the login request to Vault to obtain a {@link VaultToken}.
|
||||
* <p>
|
||||
* {@link AppRoleAuthentication} can be configured for push and pull mode by setting
|
||||
* {@link AppRoleAuthenticationOptions#getSecretId()}.
|
||||
@@ -37,23 +38,27 @@ import org.springframework.vault.support.VaultToken;
|
||||
* @author Mark Paluch
|
||||
* @see AppRoleAuthenticationOptions
|
||||
* @see VaultClient
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/approle.html">Auth Backend: AppRole</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/approle.html">Auth Backend:
|
||||
* AppRole</a>
|
||||
*/
|
||||
public class AppRoleAuthentication implements ClientAuthentication {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AppRoleAuthentication.class);
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(AppRoleAuthentication.class);
|
||||
|
||||
private final AppRoleAuthenticationOptions options;
|
||||
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
/**
|
||||
* Creates a {@link AppRoleAuthentication} using {@link AppRoleAuthenticationOptions} and {@link VaultClient}.
|
||||
* Creates a {@link AppRoleAuthentication} using {@link AppRoleAuthenticationOptions}
|
||||
* and {@link VaultClient}.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
public AppRoleAuthentication(AppRoleAuthenticationOptions options, VaultClient vaultClient) {
|
||||
public AppRoleAuthentication(AppRoleAuthenticationOptions options,
|
||||
VaultClient vaultClient) {
|
||||
|
||||
Assert.notNull(options, "AppRoleAuthenticationOptions must not be null");
|
||||
Assert.notNull(vaultClient, "VaultClient must not be null");
|
||||
@@ -69,13 +74,16 @@ public class AppRoleAuthentication implements ClientAuthentication {
|
||||
|
||||
private VaultToken createTokenUsingAppRole() {
|
||||
|
||||
Map<String, String> login = getAppRoleLogin(options.getRoleId(), options.getSecretId());
|
||||
Map<String, String> login = getAppRoleLogin(options.getRoleId(),
|
||||
options.getSecretId());
|
||||
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient
|
||||
.postForEntity(String.format("auth/%s/login", options.getPath()), login, VaultResponse.class);
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient.postForEntity(
|
||||
String.format("auth/%s/login", options.getPath()), login,
|
||||
VaultResponse.class);
|
||||
|
||||
if (!entity.isSuccessful()) {
|
||||
throw new VaultException(String.format("Cannot login using AppRole: %s", entity.getMessage()));
|
||||
throw new VaultException(String.format("Cannot login using AppRole: %s",
|
||||
entity.getMessage()));
|
||||
}
|
||||
|
||||
logger.debug("Login successful using AppRole authentication");
|
||||
|
||||
@@ -20,8 +20,9 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* Authentication options for {@link AppRoleAuthentication}.
|
||||
* <p>
|
||||
* Authentication options provide the path, roleId and pull/push mode. {@link AppRoleAuthentication} can be
|
||||
* constructed using {@link #builder()}. Instances of this class are immutable once constructed.
|
||||
* Authentication options provide the path, roleId and pull/push mode.
|
||||
* {@link AppRoleAuthentication} can be constructed using {@link #builder()}. Instances of
|
||||
* this class are immutable once constructed.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppRoleAuthentication
|
||||
@@ -92,7 +93,8 @@ public class AppRoleAuthenticationOptions {
|
||||
|
||||
private String secretId;
|
||||
|
||||
AppRoleAuthenticationOptionsBuilder() {}
|
||||
AppRoleAuthenticationOptionsBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the mount path.
|
||||
@@ -138,7 +140,8 @@ public class AppRoleAuthenticationOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link AppRoleAuthenticationOptions} instance. Requires {@link #roleId(String)} to be configured.
|
||||
* Build a new {@link AppRoleAuthenticationOptions} instance. Requires
|
||||
* {@link #roleId(String)} to be configured.
|
||||
*
|
||||
* @return a new {@link AppRoleAuthenticationOptions}.
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
@@ -35,17 +36,19 @@ import org.springframework.web.client.RestTemplate;
|
||||
/**
|
||||
* AWS-EC2 login implementation.
|
||||
* <p>
|
||||
* AWS-EC2 login uses the EC2 identity document and a nonce to login into Vault. AWS-EC2 login obtains the PKCS#7 signed
|
||||
* EC2 identity document and generates a {@link #createNonce() nonce}. Instances of this class are immutable once
|
||||
* constructed.
|
||||
* AWS-EC2 login uses the EC2 identity document and a nonce to login into Vault. AWS-EC2
|
||||
* login obtains the PKCS#7 signed EC2 identity document and generates a
|
||||
* {@link #createNonce() nonce}. Instances of this class are immutable once constructed.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AwsEc2AuthenticationOptions
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/aws-ec2.html">Auth Backend: aws-ec2</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/aws-ec2.html">Auth Backend:
|
||||
* aws-ec2</a>
|
||||
*/
|
||||
public class AwsEc2Authentication implements ClientAuthentication {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AwsEc2Authentication.class);
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(AwsEc2Authentication.class);
|
||||
|
||||
private final AwsEc2AuthenticationOptions options;
|
||||
|
||||
@@ -61,18 +64,21 @@ public class AwsEc2Authentication implements ClientAuthentication {
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
public AwsEc2Authentication(VaultClient vaultClient) {
|
||||
this(AwsEc2AuthenticationOptions.DEFAULT, vaultClient, vaultClient.getRestTemplate());
|
||||
this(AwsEc2AuthenticationOptions.DEFAULT, vaultClient, vaultClient
|
||||
.getRestTemplate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AwsEc2Authentication} specifying {@link AwsEc2AuthenticationOptions}, {@link VaultClient} and
|
||||
* a {@link RestTemplate}.
|
||||
* Creates a new {@link AwsEc2Authentication} specifying
|
||||
* {@link AwsEc2AuthenticationOptions}, {@link VaultClient} and a {@link RestTemplate}
|
||||
* .
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
* @param restTemplate must not be {@literal null}.
|
||||
*/
|
||||
public AwsEc2Authentication(AwsEc2AuthenticationOptions options, VaultClient vaultClient, RestTemplate restTemplate) {
|
||||
public AwsEc2Authentication(AwsEc2AuthenticationOptions options,
|
||||
VaultClient vaultClient, RestTemplate restTemplate) {
|
||||
|
||||
Assert.notNull(options, "AwsEc2AuthenticationOptions must not be null");
|
||||
Assert.notNull(vaultClient, "VaultEndpoint must not be null");
|
||||
@@ -95,10 +101,12 @@ public class AwsEc2Authentication implements ClientAuthentication {
|
||||
|
||||
Map<String, String> login = getEc2Login();
|
||||
|
||||
VaultResponseEntity<VaultResponse> entity = this.vaultClient.postForEntity(path, login, VaultResponse.class);
|
||||
VaultResponseEntity<VaultResponse> entity = this.vaultClient.postForEntity(path,
|
||||
login, VaultResponse.class);
|
||||
|
||||
if (!entity.isSuccessful()) {
|
||||
throw new VaultException(String.format("Cannot login using AWS-EC2: %s", entity.getMessage()));
|
||||
throw new VaultException(String.format("Cannot login using AWS-EC2: %s",
|
||||
entity.getMessage()));
|
||||
}
|
||||
|
||||
VaultResponse body = entity.getBody();
|
||||
@@ -106,10 +114,13 @@ public class AwsEc2Authentication implements ClientAuthentication {
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
if (body.getAuth().get("metadata") instanceof Map) {
|
||||
Map<Object, Object> metadata = (Map<Object, Object>) body.getAuth().get("metadata");
|
||||
logger.debug(String.format("Login successful using AWS-EC2 authentication for instance %s, AMI %s",
|
||||
metadata.get("instance_id"), metadata.get("instance_id")));
|
||||
} else {
|
||||
Map<Object, Object> metadata = (Map<Object, Object>) body.getAuth().get(
|
||||
"metadata");
|
||||
logger.debug(String
|
||||
.format("Login successful using AWS-EC2 authentication for instance %s, AMI %s",
|
||||
metadata.get("instance_id"), metadata.get("instance_id")));
|
||||
}
|
||||
else {
|
||||
logger.debug("Login successful using AWS-EC2 authentication");
|
||||
}
|
||||
}
|
||||
@@ -132,15 +143,18 @@ public class AwsEc2Authentication implements ClientAuthentication {
|
||||
login.put("nonce", new String(this.nonce.get()));
|
||||
|
||||
try {
|
||||
String pkcs7 = restTemplate.getForObject(options.getIdentityDocumentUri(), String.class);
|
||||
String pkcs7 = restTemplate.getForObject(options.getIdentityDocumentUri(),
|
||||
String.class);
|
||||
if (StringUtils.hasText(pkcs7)) {
|
||||
login.put("pkcs7", pkcs7.replaceAll("\\r", "").replace("\\n", ""));
|
||||
}
|
||||
|
||||
return login;
|
||||
} catch (RestClientException e) {
|
||||
throw new VaultException(
|
||||
String.format("Cannot obtain Identity Document from %s", options.getIdentityDocumentUri()), e);
|
||||
}
|
||||
catch (RestClientException e) {
|
||||
throw new VaultException(String.format(
|
||||
"Cannot obtain Identity Document from %s",
|
||||
options.getIdentityDocumentUri()), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* Authentication options for {@link AwsEc2Authentication}.
|
||||
* <p>
|
||||
* Authentication options provide the path, the Identity Document URI and an optional role.
|
||||
* {@link AwsEc2AuthenticationOptions} can be constructed using {@link #builder()}. Instances of this class are
|
||||
* immutable once constructed.
|
||||
* Authentication options provide the path, the Identity Document URI and an optional
|
||||
* role. {@link AwsEc2AuthenticationOptions} can be constructed using {@link #builder()}.
|
||||
* Instances of this class are immutable once constructed.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AwsEc2Authentication
|
||||
@@ -38,7 +38,8 @@ public class AwsEc2AuthenticationOptions {
|
||||
public final static String DEFAULT_AWS_AUTHENTICATION_PATH = "aws-ec2";
|
||||
|
||||
/**
|
||||
* Default {@link AwsEc2AuthenticationOptions} using {@link #DEFAULT_AWS_AUTHENTICATION_PATH} and
|
||||
* Default {@link AwsEc2AuthenticationOptions} using
|
||||
* {@link #DEFAULT_AWS_AUTHENTICATION_PATH} and
|
||||
* {@link #DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI}.
|
||||
*/
|
||||
public final static AwsEc2AuthenticationOptions DEFAULT = new AwsEc2AuthenticationOptions();
|
||||
@@ -106,7 +107,8 @@ public class AwsEc2AuthenticationOptions {
|
||||
private URI identityDocumentUri = DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI;
|
||||
private String role;
|
||||
|
||||
AwsEc2AuthenticationOptionsBuilder() {}
|
||||
AwsEc2AuthenticationOptionsBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the mount path.
|
||||
@@ -129,15 +131,17 @@ public class AwsEc2AuthenticationOptions {
|
||||
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
|
||||
* @see #DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI
|
||||
*/
|
||||
public AwsEc2AuthenticationOptionsBuilder identityDocumentUri(URI identityDocumentUri) {
|
||||
public AwsEc2AuthenticationOptionsBuilder identityDocumentUri(
|
||||
URI identityDocumentUri) {
|
||||
|
||||
this.identityDocumentUri = identityDocumentUri;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the name of the role against which the login is being attempted.If role is not specified, then the
|
||||
* login endpoint looks for a role bearing the name of the AMI ID of the EC2 instance that is trying to login.
|
||||
* Configure the name of the role against which the login is being attempted.If
|
||||
* role is not specified, then the login endpoint looks for a role bearing the
|
||||
* name of the AMI ID of the EC2 instance that is trying to login.
|
||||
*
|
||||
* @param role may be empty or {@literal null}.
|
||||
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
|
||||
|
||||
@@ -19,15 +19,17 @@ import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* {@link ClientAuthentication} provides {@link VaultToken} to be used for authenticated Vault access. Implementing
|
||||
* classes usually use a login method to login and return a {@link VaultToken} when implementing {@link #login()}.
|
||||
* {@link ClientAuthentication} provides {@link VaultToken} to be used for authenticated
|
||||
* Vault access. Implementing classes usually use a login method to login and return a
|
||||
* {@link VaultToken} when implementing {@link #login()}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface ClientAuthentication {
|
||||
|
||||
/**
|
||||
* Return a {@link VaultToken}. This method can optionally log into Vault to obtain a {@link VaultToken token}.
|
||||
* Return a {@link VaultToken}. This method can optionally log into Vault to obtain a
|
||||
* {@link VaultToken token}.
|
||||
*
|
||||
* @return a {@link VaultToken}.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.Collections;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
@@ -33,7 +34,8 @@ import org.springframework.vault.support.VaultToken;
|
||||
*/
|
||||
public class ClientCertificateAuthentication implements ClientAuthentication {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ClientCertificateAuthentication.class);
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(ClientCertificateAuthentication.class);
|
||||
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
@@ -56,11 +58,13 @@ public class ClientCertificateAuthentication implements ClientAuthentication {
|
||||
|
||||
private VaultToken createTokenUsingTlsCertAuthentication(String path) {
|
||||
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient.postForEntity(String.format("auth/%s/login", path),
|
||||
Collections.emptyMap(), VaultResponse.class);
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient.postForEntity(
|
||||
String.format("auth/%s/login", path), Collections.emptyMap(),
|
||||
VaultResponse.class);
|
||||
|
||||
if (!entity.isSuccessful()) {
|
||||
throw new VaultException(String.format("Cannot login using TLS certificates: %s", entity.getMessage()));
|
||||
throw new VaultException(String.format(
|
||||
"Cannot login using TLS certificates: %s", entity.getMessage()));
|
||||
}
|
||||
|
||||
logger.debug("Login successful using TLS certificates");
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
@@ -29,22 +30,23 @@ import org.springframework.vault.support.VaultToken;
|
||||
/**
|
||||
* Cubbyhole {@link ClientAuthentication} implementation.
|
||||
* <p>
|
||||
* Cubbyhole authentication uses Vault primitives to provide a secured authentication workflow. Cubbyhole authentication
|
||||
* uses {@link VaultToken tokens} as primary login method. An ephemeral token is used to obtain a second, login
|
||||
* {@link VaultToken} from Vault's Cubbyhole secret backend. The login token is usually longer-lived and used to
|
||||
* interact with Vault. The login token can be retrieved either from a wrapped response or from the {@code data}
|
||||
* section.
|
||||
* Cubbyhole authentication uses Vault primitives to provide a secured authentication
|
||||
* workflow. Cubbyhole authentication uses {@link VaultToken tokens} as primary login
|
||||
* method. An ephemeral token is used to obtain a second, login {@link VaultToken} from
|
||||
* Vault's Cubbyhole secret backend. The login token is usually longer-lived and used to
|
||||
* interact with Vault. The login token can be retrieved either from a wrapped response or
|
||||
* from the {@code data} section.
|
||||
* <h2>Wrapped token response usage</h2> <strong>Create a Token</strong>
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
$ vault token-create -wrap-ttl="10m"
|
||||
Key Value
|
||||
--- -----
|
||||
wrapping_token: 397ccb93-ff6c-b17b-9389-380b01ca2645
|
||||
wrapping_token_ttl: 0h10m0s
|
||||
wrapping_token_creation_time: 2016-09-18 20:29:48.652957077 +0200 CEST
|
||||
wrapped_accessor: 46b6aebb-187f-932a-26d7-4f3d86a68319
|
||||
* $ vault token-create -wrap-ttl="10m"
|
||||
* Key Value
|
||||
* --- -----
|
||||
* wrapping_token: 397ccb93-ff6c-b17b-9389-380b01ca2645
|
||||
* wrapping_token_ttl: 0h10m0s
|
||||
* wrapping_token_creation_time: 2016-09-18 20:29:48.652957077 +0200 CEST
|
||||
* wrapped_accessor: 46b6aebb-187f-932a-26d7-4f3d86a68319
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
@@ -52,12 +54,12 @@ import org.springframework.vault.support.VaultToken;
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions
|
||||
.builder()
|
||||
.initialToken(VaultToken.of("397ccb93-ff6c-b17b-9389-380b01ca2645"))
|
||||
.wrapped()
|
||||
.build();
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
* CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions
|
||||
* .builder()
|
||||
* .initialToken(VaultToken.of("397ccb93-ff6c-b17b-9389-380b01ca2645"))
|
||||
* .wrapped()
|
||||
* .build();
|
||||
* CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
@@ -65,26 +67,26 @@ import org.springframework.vault.support.VaultToken;
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
$ vault token-create
|
||||
Key Value
|
||||
--- -----
|
||||
token f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819
|
||||
token_accessor 4eee9bd9-81bb-06d6-af01-723c54a72148
|
||||
token_duration 0s
|
||||
token_renewable false
|
||||
token_policies [root]
|
||||
|
||||
$ token-create -use-limit=2 -orphan -no-default-policy -policy=none
|
||||
Key Value
|
||||
--- -----
|
||||
token 895cb88b-aef4-0e33-ba65-d50007290780
|
||||
token_accessor e84b661c-8aa8-2286-b788-f258f30c8325
|
||||
token_duration 0s
|
||||
token_renewable false
|
||||
token_policies [none]
|
||||
|
||||
$ export VAULT_TOKEN=895cb88b-aef4-0e33-ba65-d50007290780
|
||||
$ vault write cubbyhole/token token=f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819
|
||||
* $ vault token-create
|
||||
* Key Value
|
||||
* --- -----
|
||||
* token f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819
|
||||
* token_accessor 4eee9bd9-81bb-06d6-af01-723c54a72148
|
||||
* token_duration 0s
|
||||
* token_renewable false
|
||||
* token_policies [root]
|
||||
*
|
||||
* $ token-create -use-limit=2 -orphan -no-default-policy -policy=none
|
||||
* Key Value
|
||||
* --- -----
|
||||
* token 895cb88b-aef4-0e33-ba65-d50007290780
|
||||
* token_accessor e84b661c-8aa8-2286-b788-f258f30c8325
|
||||
* token_duration 0s
|
||||
* token_renewable false
|
||||
* token_policies [none]
|
||||
*
|
||||
* $ export VAULT_TOKEN=895cb88b-aef4-0e33-ba65-d50007290780
|
||||
* $ vault write cubbyhole/token token=f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
@@ -92,36 +94,42 @@ import org.springframework.vault.support.VaultToken;
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions
|
||||
.builder()
|
||||
.initialToken(VaultToken.of("895cb88b-aef4-0e33-ba65-d50007290780"))
|
||||
.path("cubbyhole/token")
|
||||
.build();
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
* CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions
|
||||
* .builder()
|
||||
* .initialToken(VaultToken.of("895cb88b-aef4-0e33-ba65-d50007290780"))
|
||||
* .path("cubbyhole/token")
|
||||
* .build();
|
||||
* CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see CubbyholeAuthenticationOptions
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">Auth Backend: Token</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/secrets/cubbyhole/index.html">Cubbyhole Secret Backend</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/concepts/response-wrapping.html">Response Wrapping</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/secrets/cubbyhole/index.html">Cubbyhole
|
||||
* Secret Backend</a>
|
||||
* @see <a
|
||||
* href="https://www.vaultproject.io/docs/concepts/response-wrapping.html">Response
|
||||
* Wrapping</a>
|
||||
*/
|
||||
public class CubbyholeAuthentication implements ClientAuthentication {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(CubbyholeAuthentication.class);
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(CubbyholeAuthentication.class);
|
||||
|
||||
private final CubbyholeAuthenticationOptions options;
|
||||
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
/**
|
||||
* Create a new {@link CubbyholeAuthentication} given {@link CubbyholeAuthenticationOptions} and {@link VaultClient}.
|
||||
* Create a new {@link CubbyholeAuthentication} given
|
||||
* {@link CubbyholeAuthenticationOptions} and {@link VaultClient}.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
public CubbyholeAuthentication(CubbyholeAuthenticationOptions options, VaultClient vaultClient) {
|
||||
public CubbyholeAuthentication(CubbyholeAuthenticationOptions options,
|
||||
VaultClient vaultClient) {
|
||||
|
||||
Assert.notNull(options, "CubbyholeAuthenticationOptions must not be null");
|
||||
Assert.notNull(vaultClient, "VaultClient must not be null");
|
||||
@@ -133,8 +141,8 @@ public class CubbyholeAuthentication implements ClientAuthentication {
|
||||
@Override
|
||||
public VaultToken login() throws VaultException {
|
||||
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient.getForEntity(options.getPath(), options.getInitialToken(),
|
||||
VaultResponse.class);
|
||||
VaultResponseEntity<VaultResponse> entity = vaultClient.getForEntity(
|
||||
options.getPath(), options.getInitialToken(), VaultResponse.class);
|
||||
|
||||
if (entity.isSuccessful() && entity.hasBody()) {
|
||||
|
||||
@@ -149,21 +157,26 @@ public class CubbyholeAuthentication implements ClientAuthentication {
|
||||
}
|
||||
}
|
||||
|
||||
throw new VaultException(
|
||||
String.format("Cannot retrieve Token from cubbyhole: %s %s", entity.getStatusCode(), entity.getMessage()));
|
||||
throw new VaultException(String.format(
|
||||
"Cannot retrieve Token from cubbyhole: %s %s", entity.getStatusCode(),
|
||||
entity.getMessage()));
|
||||
}
|
||||
|
||||
private VaultToken getToken(VaultResponseEntity<VaultResponse> entity, Map<String, Object> data) {
|
||||
private VaultToken getToken(VaultResponseEntity<VaultResponse> entity,
|
||||
Map<String, Object> data) {
|
||||
|
||||
if (options.isWrappedToken()) {
|
||||
|
||||
VaultResponse response = vaultClient.unwrap((String) data.get("response"), VaultResponse.class);
|
||||
VaultResponse response = vaultClient.unwrap((String) data.get("response"),
|
||||
VaultResponse.class);
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
|
||||
if (data == null || data.isEmpty()) {
|
||||
throw new VaultException(String
|
||||
.format("Cannot retrieve Token from cubbyhole: Response at %s does not contain a token", entity.getUri()));
|
||||
throw new VaultException(
|
||||
String.format(
|
||||
"Cannot retrieve Token from cubbyhole: Response at %s does not contain a token",
|
||||
entity.getUri()));
|
||||
}
|
||||
|
||||
if (data.size() == 1) {
|
||||
@@ -171,7 +184,9 @@ public class CubbyholeAuthentication implements ClientAuthentication {
|
||||
return VaultToken.of(token);
|
||||
}
|
||||
|
||||
throw new VaultException(String.format(
|
||||
"Cannot retrieve Token from cubbyhole: Response at %s does not contain an unique token", entity.getUri()));
|
||||
throw new VaultException(
|
||||
String.format(
|
||||
"Cannot retrieve Token from cubbyhole: Response at %s does not contain an unique token",
|
||||
entity.getUri()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ import org.springframework.vault.support.VaultToken;
|
||||
/**
|
||||
* Authentication options for {@link CubbyholeAuthentication}.
|
||||
* <p>
|
||||
* Authentication options provide the path below cubbyhole and the cubbyhole mode. Instances of this class are immutable
|
||||
* once constructed.
|
||||
* Authentication options provide the path below cubbyhole and the cubbyhole mode.
|
||||
* Instances of this class are immutable once constructed.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see CubbyholeAuthentication
|
||||
@@ -45,7 +45,8 @@ public class CubbyholeAuthenticationOptions {
|
||||
*/
|
||||
private final boolean wrappedToken;
|
||||
|
||||
private CubbyholeAuthenticationOptions(VaultToken initialToken, String path, boolean wrappedToken) {
|
||||
private CubbyholeAuthenticationOptions(VaultToken initialToken, String path,
|
||||
boolean wrappedToken) {
|
||||
|
||||
this.initialToken = initialToken;
|
||||
this.path = path;
|
||||
@@ -74,8 +75,9 @@ public class CubbyholeAuthenticationOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} indicates that the Cubbyhole response contains a wrapped token, otherwise {@literal false}
|
||||
* to expect a token in the {@literal data} response.
|
||||
* @return {@literal true} indicates that the Cubbyhole response contains a wrapped
|
||||
* token, otherwise {@literal false} to expect a token in the {@literal data}
|
||||
* response.
|
||||
*/
|
||||
public boolean isWrappedToken() {
|
||||
return wrappedToken;
|
||||
@@ -92,7 +94,8 @@ public class CubbyholeAuthenticationOptions {
|
||||
|
||||
private boolean wrappedToken;
|
||||
|
||||
CubbyholeAuthenticationOptionsBuilder() {}
|
||||
CubbyholeAuthenticationOptionsBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the initial {@link VaultToken} to access Cubbyhole.
|
||||
@@ -109,7 +112,8 @@ public class CubbyholeAuthenticationOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the cubbyhole path, such as {@code cubbyhole/token}. Expects a token in the {@code data} response.
|
||||
* Configure the cubbyhole path, such as {@code cubbyhole/token}. Expects a token
|
||||
* in the {@code data} response.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @return {@code this} {@link CubbyholeAuthenticationOptionsBuilder}.
|
||||
@@ -135,8 +139,8 @@ public class CubbyholeAuthenticationOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link CubbyholeAuthenticationOptions} instance. Requires {@link #path(String)} or
|
||||
* {@link #wrapped()} to be configured.
|
||||
* Build a new {@link CubbyholeAuthenticationOptions} instance. Requires
|
||||
* {@link #path(String)} or {@link #wrapped()} to be configured.
|
||||
*
|
||||
* @return a new {@link CubbyholeAuthenticationOptions}.
|
||||
*/
|
||||
|
||||
@@ -20,8 +20,8 @@ import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* Mechanism to generate a SHA-256 hashed and hex-encoded representation of the IP address. Can be calculated with
|
||||
* {@code echo -n 192.168.99.1 | sha256sum}.
|
||||
* Mechanism to generate a SHA-256 hashed and hex-encoded representation of the IP
|
||||
* address. Can be calculated with {@code echo -n 192.168.99.1 | sha256sum}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
@@ -32,7 +32,8 @@ public class IpAddressUserId implements AppIdUserIdMechanism {
|
||||
public String createUserId() {
|
||||
try {
|
||||
return Sha256.toSha256(InetAddress.getLocalHost().getHostAddress());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
@@ -36,15 +37,18 @@ import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* Lifecycle-aware Session Manager. This {@link SessionManager} obtains tokens from a {@link ClientAuthentication} upon
|
||||
* {@link #getSessionToken() request}. Tokens are renewed asynchronously if a token has a lease duration. This happens 5
|
||||
* seconds before the token expires, see {@link #REFRESH_PERIOD_BEFORE_EXPIRY}.
|
||||
* Lifecycle-aware Session Manager. This {@link SessionManager} obtains tokens from a
|
||||
* {@link ClientAuthentication} upon {@link #getSessionToken() request}. Tokens are
|
||||
* renewed asynchronously if a token has a lease duration. This happens 5 seconds before
|
||||
* the token expires, see {@link #REFRESH_PERIOD_BEFORE_EXPIRY}.
|
||||
* <p>
|
||||
* This {@link SessionManager} also implements {@link DisposableBean} to revoke the {@link LoginToken} once it's not
|
||||
* required anymore. Token revocation will stop regular token refresh.
|
||||
* This {@link SessionManager} also implements {@link DisposableBean} to revoke the
|
||||
* {@link LoginToken} once it's not required anymore. Token revocation will stop regular
|
||||
* token refresh.
|
||||
* <p>
|
||||
* If Token renewal runs into a client-side error, it assumes the token was revoked/expired and discards the token state
|
||||
* so the next attempt will lead to another login attempt.
|
||||
* If Token renewal runs into a client-side error, it assumes the token was
|
||||
* revoked/expired and discards the token state so the next attempt will lead to another
|
||||
* login attempt.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see LoginToken
|
||||
@@ -55,7 +59,8 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
|
||||
|
||||
public static final int REFRESH_PERIOD_BEFORE_EXPIRY = 5;
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(LifecycleAwareSessionManager.class);
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(LifecycleAwareSessionManager.class);
|
||||
|
||||
private final ClientAuthentication clientAuthentication;
|
||||
private final VaultClient vaultClient;
|
||||
@@ -65,15 +70,15 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
|
||||
private volatile VaultToken token;
|
||||
|
||||
/**
|
||||
* Create a {@link LifecycleAwareSessionManager} given {@link ClientAuthentication}, {@link AsyncTaskExecutor} and
|
||||
* {@link VaultClient}.
|
||||
* Create a {@link LifecycleAwareSessionManager} given {@link ClientAuthentication},
|
||||
* {@link AsyncTaskExecutor} and {@link VaultClient}.
|
||||
*
|
||||
* @param clientAuthentication must not be {@literal null}.
|
||||
* @param taskExecutor must not be {@literal null}.
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
public LifecycleAwareSessionManager(ClientAuthentication clientAuthentication, AsyncTaskExecutor taskExecutor,
|
||||
VaultClient vaultClient) {
|
||||
public LifecycleAwareSessionManager(ClientAuthentication clientAuthentication,
|
||||
AsyncTaskExecutor taskExecutor, VaultClient vaultClient) {
|
||||
|
||||
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
|
||||
Assert.notNull(taskExecutor, "AsyncTaskExecutor must not be null");
|
||||
@@ -91,21 +96,24 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
|
||||
this.token = null;
|
||||
|
||||
if (token instanceof LoginToken) {
|
||||
VaultResponseEntity<Map> response = vaultClient.postForEntity("auth/token/revoke-self", token, null, Map.class);
|
||||
VaultResponseEntity<Map> response = vaultClient.postForEntity(
|
||||
"auth/token/revoke-self", token, null, Map.class);
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
logger.warn("Cannot revoke VaultToken: {}", buildExceptionMessage(response));
|
||||
logger.warn("Cannot revoke VaultToken: {}",
|
||||
buildExceptionMessage(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a token refresh. Creates a new token if no token was obtained before. If a token was obtained before, it
|
||||
* uses self-renewal to renew the current token. Client-side errors (like permission denied) indicate the token cannot
|
||||
* be renewed because it's expired or simply not found.
|
||||
* Performs a token refresh. Creates a new token if no token was obtained before. If a
|
||||
* token was obtained before, it uses self-renewal to renew the current token.
|
||||
* Client-side errors (like permission denied) indicate the token cannot be renewed
|
||||
* because it's expired or simply not found.
|
||||
*
|
||||
* @return {@literal true} if the refresh was successful. {@literal false} if a new token was obtained or refresh
|
||||
* failed.
|
||||
* @return {@literal true} if the refresh was successful. {@literal false} if a new
|
||||
* token was obtained or refresh failed.
|
||||
*/
|
||||
protected boolean renewToken() {
|
||||
|
||||
@@ -116,12 +124,14 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
|
||||
return false;
|
||||
}
|
||||
|
||||
VaultResponseEntity<Map> response = vaultClient.postForEntity("auth/token/renew-self", token, null, Map.class);
|
||||
VaultResponseEntity<Map> response = vaultClient.postForEntity(
|
||||
"auth/token/renew-self", token, null, Map.class);
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
|
||||
if (response.getStatusCode().is4xxClientError()) {
|
||||
logger.debug("Cannot refresh token, resetting token and performing re-login: {}",
|
||||
logger.debug(
|
||||
"Cannot refresh token, resetting token and performing re-login: {}",
|
||||
buildExceptionMessage(response));
|
||||
token = null;
|
||||
return false;
|
||||
@@ -169,19 +179,23 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
|
||||
logger.info("Scheduling Token renewal");
|
||||
|
||||
LoginToken loginToken = (LoginToken) token;
|
||||
final int seconds = NumberUtils.convertNumberToTargetClass(
|
||||
Math.max(1, loginToken.getLeaseDuration() - REFRESH_PERIOD_BEFORE_EXPIRY), Integer.class);
|
||||
final int seconds = NumberUtils
|
||||
.convertNumberToTargetClass(
|
||||
Math.max(1, loginToken.getLeaseDuration()
|
||||
- REFRESH_PERIOD_BEFORE_EXPIRY), Integer.class);
|
||||
|
||||
final Runnable task = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (LifecycleAwareSessionManager.this.token != null && isTokenRenewable()) {
|
||||
if (LifecycleAwareSessionManager.this.token != null
|
||||
&& isTokenRenewable()) {
|
||||
if (renewToken()) {
|
||||
scheduleRenewal();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("Cannot renew VaultToken", e);
|
||||
}
|
||||
}
|
||||
@@ -196,12 +210,15 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// TODO: Revisit this approach since it blocks a thread. Spinning up a managed
|
||||
// TaskScheduler just for once-in-a-while token renewal seemed a bit over-sophisticated
|
||||
// TODO: Revisit this approach since it blocks a thread. Spinning up a
|
||||
// managed
|
||||
// TaskScheduler just for once-in-a-while token renewal seemed a bit
|
||||
// over-sophisticated
|
||||
// that's why we emulate a scheduler by blocking a Thread resource
|
||||
Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
|
||||
task.run();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
@@ -215,14 +232,17 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
|
||||
private static String buildExceptionMessage(VaultResponseEntity<?> response) {
|
||||
|
||||
if (StringUtils.hasText(response.getMessage())) {
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(), response.getUri(), response.getMessage());
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(),
|
||||
response.getUri(), response.getMessage());
|
||||
}
|
||||
|
||||
return String.format("Status %s URI %s", response.getStatusCode(), response.getUri());
|
||||
return String.format("Status %s URI %s", response.getStatusCode(),
|
||||
response.getUri());
|
||||
}
|
||||
|
||||
/**
|
||||
* This one-shot trigger creates only one execution time to trigger an execution only once.
|
||||
* This one-shot trigger creates only one execution time to trigger an execution only
|
||||
* once.
|
||||
*/
|
||||
private static class OneShotTrigger implements Trigger {
|
||||
|
||||
@@ -237,7 +257,8 @@ public class LifecycleAwareSessionManager implements SessionManager, DisposableB
|
||||
public Date nextExecutionTime(TriggerContext triggerContext) {
|
||||
|
||||
if (fired.compareAndSet(false, true)) {
|
||||
return new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(seconds));
|
||||
return new Date(System.currentTimeMillis()
|
||||
+ TimeUnit.SECONDS.toMillis(seconds));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import lombok.ToString;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Value object for a Vault token obtained by a login method.
|
||||
*
|
||||
|
||||
@@ -24,13 +24,15 @@ import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Mechanism to generate a UserId based on the Mac address. {@link MacAddressUserId} creates a hex-encoded
|
||||
* representation of the Mac address without any separators (0123456789AB). A network interface hint can be specified
|
||||
* optionally to select a network interface (index/name).
|
||||
* Mechanism to generate a UserId based on the Mac address. {@link MacAddressUserId}
|
||||
* creates a hex-encoded representation of the Mac address without any separators
|
||||
* (0123456789AB). A network interface hint can be specified optionally to select a
|
||||
* network interface (index/name).
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see AppIdUserIdMechanism
|
||||
@@ -50,22 +52,24 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MacAddressUserId} using a {@code networkInterfaceIndex}. The index is applied to
|
||||
* {@link NetworkInterface#getNetworkInterfaces()} to obtain the desired network interface.
|
||||
* Creates a new {@link MacAddressUserId} using a {@code networkInterfaceIndex}. The
|
||||
* index is applied to {@link NetworkInterface#getNetworkInterfaces()} to obtain the
|
||||
* desired network interface.
|
||||
*
|
||||
* @param networkInterfaceIndex must be greater or equal to zero.
|
||||
*/
|
||||
public MacAddressUserId(int networkInterfaceIndex) {
|
||||
|
||||
Assert.isTrue(networkInterfaceIndex >= 0, "NetworkInterfaceIndex must be greater or equal to 0");
|
||||
Assert.isTrue(networkInterfaceIndex >= 0,
|
||||
"NetworkInterfaceIndex must be greater or equal to 0");
|
||||
|
||||
this.networkInterfaceHint = "" + networkInterfaceIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MacAddressUserId} using a {@code networkInterfaceName}. This name is compared with
|
||||
* {@link NetworkInterface#getName()} and {@link NetworkInterface#getDisplayName()} to obtain the desired network
|
||||
* interface.
|
||||
* Creates a new {@link MacAddressUserId} using a {@code networkInterfaceName}. This
|
||||
* name is compared with {@link NetworkInterface#getName()} and
|
||||
* {@link NetworkInterface#getDisplayName()} to obtain the desired network interface.
|
||||
*
|
||||
* @param networkInterfaceName must not be {@literal null}.
|
||||
*/
|
||||
@@ -82,44 +86,54 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
|
||||
try {
|
||||
|
||||
NetworkInterface networkInterface = null;
|
||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface
|
||||
.getNetworkInterfaces());
|
||||
|
||||
if (StringUtils.hasText(networkInterfaceHint)) {
|
||||
|
||||
try {
|
||||
networkInterface = getNetworkInterface(Integer.parseInt(networkInterfaceHint), interfaces);
|
||||
} catch (NumberFormatException e) {
|
||||
networkInterface = getNetworkInterface((networkInterfaceHint), interfaces);
|
||||
networkInterface = getNetworkInterface(
|
||||
Integer.parseInt(networkInterfaceHint), interfaces);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
networkInterface = getNetworkInterface((networkInterfaceHint),
|
||||
interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
if (networkInterface == null) {
|
||||
|
||||
if (StringUtils.hasText(networkInterfaceHint)) {
|
||||
log.warn(String.format("Did not find a NetworkInterface applying hint %s", networkInterfaceHint));
|
||||
log.warn(String.format(
|
||||
"Did not find a NetworkInterface applying hint %s",
|
||||
networkInterfaceHint));
|
||||
}
|
||||
|
||||
InetAddress localHost = InetAddress.getLocalHost();
|
||||
networkInterface = NetworkInterface.getByInetAddress(localHost);
|
||||
|
||||
if (networkInterface == null) {
|
||||
throw new IllegalStateException(String.format("Cannot determine NetworkInterface for %s", localHost));
|
||||
throw new IllegalStateException(String.format(
|
||||
"Cannot determine NetworkInterface for %s", localHost));
|
||||
}
|
||||
}
|
||||
|
||||
byte[] mac = networkInterface.getHardwareAddress();
|
||||
if (mac == null) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Network interface %s has no hardware address", networkInterface.getName()));
|
||||
throw new IllegalStateException(String.format(
|
||||
"Network interface %s has no hardware address",
|
||||
networkInterface.getName()));
|
||||
}
|
||||
|
||||
return Sha256.toSha256(Sha256.toHexString(mac));
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private NetworkInterface getNetworkInterface(Number hint, List<NetworkInterface> interfaces) {
|
||||
private NetworkInterface getNetworkInterface(Number hint,
|
||||
List<NetworkInterface> interfaces) {
|
||||
|
||||
if (interfaces.size() > hint.intValue() && hint.intValue() >= 0) {
|
||||
return interfaces.get(hint.intValue());
|
||||
@@ -128,10 +142,12 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
|
||||
return null;
|
||||
}
|
||||
|
||||
private NetworkInterface getNetworkInterface(String hint, List<NetworkInterface> interfaces) {
|
||||
private NetworkInterface getNetworkInterface(String hint,
|
||||
List<NetworkInterface> interfaces) {
|
||||
|
||||
for (NetworkInterface anInterface : interfaces) {
|
||||
if (hint.equals(anInterface.getDisplayName()) || hint.equals(anInterface.getName())) {
|
||||
if (hint.equals(anInterface.getDisplayName())
|
||||
|| hint.equals(anInterface.getName())) {
|
||||
return anInterface;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@ package org.springframework.vault.authentication;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* Strategy interface that encapsulates the creation and management of Vault sessions based on {@link VaultToken}.
|
||||
* Strategy interface that encapsulates the creation and management of Vault sessions
|
||||
* based on {@link VaultToken}.
|
||||
* <p>
|
||||
* {@link SessionManager} is used by {@link org.springframework.vault.core.VaultTemplate} to initiate a session.
|
||||
* Implementing classes usually use {@link ClientAuthentication} to log into Vault and obtain tokens.
|
||||
* {@link SessionManager} is used by {@link org.springframework.vault.core.VaultTemplate}
|
||||
* to initiate a session. Implementing classes usually use {@link ClientAuthentication} to
|
||||
* log into Vault and obtain tokens.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see SimpleSessionManager
|
||||
|
||||
@@ -47,16 +47,18 @@ class Sha256 {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MessageDigest instance for the given algorithm. Throws an IllegalArgumentException if <i>algorithm</i> is
|
||||
* unknown
|
||||
* Get a MessageDigest instance for the given algorithm. Throws an
|
||||
* IllegalArgumentException if <i>algorithm</i> is unknown
|
||||
*
|
||||
* @return MessageDigest instance
|
||||
* @throws IllegalArgumentException if NoSuchAlgorithmException is thrown
|
||||
*/
|
||||
private static MessageDigest getMessageDigest(String algorithm) throws IllegalArgumentException {
|
||||
private static MessageDigest getMessageDigest(String algorithm)
|
||||
throws IllegalArgumentException {
|
||||
try {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalArgumentException("No such algorithm [" + algorithm + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ import org.springframework.vault.support.VaultToken;
|
||||
/**
|
||||
* Default implementation of {@link SessionManager}.
|
||||
* <p>
|
||||
* Uses a synchronized login method to log into Vault and reuse the resulting {@link VaultToken} throughout session
|
||||
* lifetime.
|
||||
* Uses a synchronized login method to log into Vault and reuse the resulting
|
||||
* {@link VaultToken} throughout session lifetime.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see ClientAuthentication
|
||||
|
||||
@@ -27,7 +27,8 @@ import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Base class for Vault accessing helpers, defining common properties such as the {@link RestTemplate} to operate on.
|
||||
* Base class for Vault accessing helpers, defining common properties such as the
|
||||
* {@link RestTemplate} to operate on.
|
||||
* <p>
|
||||
* Not intended to be used directly. See {@link VaultClient}.
|
||||
*
|
||||
@@ -66,41 +67,49 @@ public abstract class VaultAccessor {
|
||||
return callback.doWithRestTemplate(uri, getRestTemplate());
|
||||
}
|
||||
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(URI uri, HttpMethod httpMethod, HttpEntity<?> httpEntity,
|
||||
Class<T> returnType) {
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(URI uri,
|
||||
HttpMethod httpMethod, HttpEntity<?> httpEntity, Class<T> returnType) {
|
||||
|
||||
Assert.notNull(uri, "URI must not be null");
|
||||
Assert.notNull(httpMethod, "HttpMethod must not be null");
|
||||
Assert.notNull(returnType, "Return type must not be null");
|
||||
|
||||
try {
|
||||
ResponseEntity<T> response = this.getRestTemplate().exchange(uri, httpMethod, httpEntity, returnType);
|
||||
ResponseEntity<T> response = this.getRestTemplate().exchange(uri, httpMethod,
|
||||
httpEntity, returnType);
|
||||
|
||||
return new VaultResponseEntity<S>((S) response.getBody(), response.getStatusCode(), uri,
|
||||
response.getStatusCode().getReasonPhrase());
|
||||
} catch (HttpStatusCodeException e) {
|
||||
return new VaultResponseEntity<S>((S) response.getBody(),
|
||||
response.getStatusCode(), uri, response.getStatusCode()
|
||||
.getReasonPhrase());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
return handleCodeException(uri, e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(URI uri, HttpMethod httpMethod, HttpEntity<?> httpEntity,
|
||||
ParameterizedTypeReference<T> returnType) {
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(URI uri,
|
||||
HttpMethod httpMethod, HttpEntity<?> httpEntity,
|
||||
ParameterizedTypeReference<T> returnType) {
|
||||
|
||||
Assert.notNull(uri, "URI must not be null");
|
||||
Assert.notNull(httpMethod, "HttpMethod must not be null");
|
||||
Assert.notNull(returnType, "Return type must not be null");
|
||||
|
||||
try {
|
||||
ResponseEntity<T> response = this.getRestTemplate().exchange(uri, httpMethod, httpEntity, returnType);
|
||||
ResponseEntity<T> response = this.getRestTemplate().exchange(uri, httpMethod,
|
||||
httpEntity, returnType);
|
||||
|
||||
return new VaultResponseEntity<S>((S) response.getBody(), response.getStatusCode(), uri,
|
||||
response.getStatusCode().getReasonPhrase());
|
||||
} catch (HttpStatusCodeException e) {
|
||||
return new VaultResponseEntity<S>((S) response.getBody(),
|
||||
response.getStatusCode(), uri, response.getStatusCode()
|
||||
.getReasonPhrase());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
return handleCodeException(uri, e);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> VaultResponseEntity<T> handleCodeException(URI uri, HttpStatusCodeException e) {
|
||||
private <T> VaultResponseEntity<T> handleCodeException(URI uri,
|
||||
HttpStatusCodeException e) {
|
||||
|
||||
String message = e.getResponseBodyAsString();
|
||||
|
||||
|
||||
@@ -39,12 +39,14 @@ import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Implementation of the low-level Vault client. This client uses the Vault HTTP API to issue requests using different
|
||||
* {@link HttpMethod HTTP methods}. {@link VaultClient} is configured with an {@link VaultEndpoint} and
|
||||
* {@link RestTemplate}. It does not maintain any session or token state. See {@link VaultTemplate} and
|
||||
* {@link org.springframework.vault.authentication.SessionManager} for authenticated and stateful Vault access.
|
||||
* {@link VaultClient} encapsulates base URI and path construction and uses {@link VaultAccessor} for request and error
|
||||
* handling by returning {@link VaultResponseEntity} for requests.
|
||||
* Implementation of the low-level Vault client. This client uses the Vault HTTP API to
|
||||
* issue requests using different {@link HttpMethod HTTP methods}. {@link VaultClient} is
|
||||
* configured with an {@link VaultEndpoint} and {@link RestTemplate}. It does not maintain
|
||||
* any session or token state. See {@link VaultTemplate} and
|
||||
* {@link org.springframework.vault.authentication.SessionManager} for authenticated and
|
||||
* stateful Vault access. {@link VaultClient} encapsulates base URI and path construction
|
||||
* and uses {@link VaultAccessor} for request and error handling by returning
|
||||
* {@link VaultResponseEntity} for requests.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see VaultResponseEntity
|
||||
@@ -59,7 +61,8 @@ public class VaultClient extends VaultAccessor {
|
||||
private final VaultEndpoint endpoint;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultClient} with a default a {@link RestTemplate} and {@link VaultEndpoint}.
|
||||
* Creates a new {@link VaultClient} with a default a {@link RestTemplate} and
|
||||
* {@link VaultEndpoint}.
|
||||
*
|
||||
* @see VaultEndpoint
|
||||
*/
|
||||
@@ -68,7 +71,8 @@ public class VaultClient extends VaultAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultClient} for a {@link ClientHttpRequestFactory} and {@link VaultEndpoint}.
|
||||
* Creates a new {@link VaultClient} for a {@link ClientHttpRequestFactory} and
|
||||
* {@link VaultEndpoint}.
|
||||
*
|
||||
* @param requestFactory must not be {@literal null}.
|
||||
* @param endpoint must not be {@literal null}.
|
||||
@@ -82,9 +86,11 @@ public class VaultClient extends VaultAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link RestTemplate} using an interceptor given a {@link ClientHttpRequestFactory}. This forces
|
||||
* {@link RestTemplate} to create the body representation instead of streaming the body to the TCP channel. Streaming
|
||||
* the body without knowing the size in advance will skip the {@link HttpHeaders#CONTENT_LENGTH} makes Vault upset.
|
||||
* Create a {@link RestTemplate} using an interceptor given a
|
||||
* {@link ClientHttpRequestFactory}. This forces {@link RestTemplate} to create the
|
||||
* body representation instead of streaming the body to the TCP channel. Streaming the
|
||||
* body without knowing the size in advance will skip the
|
||||
* {@link HttpHeaders#CONTENT_LENGTH} makes Vault upset.
|
||||
*
|
||||
* @param requestFactory must not be {@literal null}.
|
||||
* @return the {@link RestTemplate}
|
||||
@@ -97,8 +103,8 @@ public class VaultClient extends VaultAccessor {
|
||||
restTemplate.getInterceptors().add(new ClientHttpRequestInterceptor() {
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
|
||||
throws IOException {
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution) throws IOException {
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
});
|
||||
@@ -107,7 +113,8 @@ public class VaultClient extends VaultAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultClient} for a {@link RestTemplate} and {@link VaultEndpoint}.
|
||||
* Creates a new {@link VaultClient} for a {@link RestTemplate} and
|
||||
* {@link VaultEndpoint}.
|
||||
*
|
||||
* @param restTemplate must not be {@literal null}.
|
||||
* @param endpoint must not be {@literal null}.
|
||||
@@ -121,19 +128,23 @@ public class VaultClient extends VaultAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a resource by GETting from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
* Retrieve a resource by GETting from the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.GET, new HttpEntity<Object>(null), responseType, null);
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path,
|
||||
Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.GET, new HttpEntity<Object>(null), responseType,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a resource by GETting from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
* Retrieve a resource by GETting from the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param vaultToken the {@link VaultToken}.
|
||||
@@ -141,14 +152,16 @@ public class VaultClient extends VaultAccessor {
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path, VaultToken vaultToken,
|
||||
Class<T> responseType) {
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path,
|
||||
VaultToken vaultToken, Class<T> responseType) {
|
||||
|
||||
return exchange(path, HttpMethod.GET, new HttpEntity<Object>(null, createHeaders(vaultToken)), responseType, null);
|
||||
return exchange(path, HttpMethod.GET, new HttpEntity<Object>(null,
|
||||
createHeaders(vaultToken)), responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a POST request using the given object to the path, and returns the response as {@link VaultResponseEntity}.
|
||||
* Issue a POST request using the given object to the path, and returns the response
|
||||
* as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param request the Object to be POSTed, may be {@code null}.
|
||||
@@ -156,12 +169,15 @@ public class VaultClient extends VaultAccessor {
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path, Object request, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.POST, new HttpEntity<Object>(request), responseType, null);
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path,
|
||||
Object request, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.POST, new HttpEntity<Object>(request),
|
||||
responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a POST request using the given object to the path, and returns the response as {@link VaultResponseEntity}.
|
||||
* Issue a POST request using the given object to the path, and returns the response
|
||||
* as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param vaultToken the {@link VaultToken}.
|
||||
@@ -170,15 +186,15 @@ public class VaultClient extends VaultAccessor {
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path, VaultToken vaultToken, Object request,
|
||||
Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.POST, new HttpEntity<Object>(request, createHeaders(vaultToken)), responseType,
|
||||
null);
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path,
|
||||
VaultToken vaultToken, Object request, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.POST, new HttpEntity<Object>(request,
|
||||
createHeaders(vaultToken)), responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new resource by PUTting the given object to the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
* Create a new resource by PUTting the given object to the path, and returns the
|
||||
* response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param request the Object to be PUT.
|
||||
@@ -186,13 +202,15 @@ public class VaultClient extends VaultAccessor {
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path, Object request, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.PUT, new HttpEntity<Object>(request), responseType, null);
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path,
|
||||
Object request, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.PUT, new HttpEntity<Object>(request),
|
||||
responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new resource by PUTting the given object to the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
* Create a new resource by PUTting the given object to the path, and returns the
|
||||
* response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param vaultToken the {@link VaultToken}.
|
||||
@@ -201,14 +219,15 @@ public class VaultClient extends VaultAccessor {
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path, VaultToken vaultToken, Object request,
|
||||
Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.PUT, new HttpEntity<Object>(request, createHeaders(vaultToken)), responseType,
|
||||
null);
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path,
|
||||
VaultToken vaultToken, Object request, Class<T> responseType) {
|
||||
return exchange(path, HttpMethod.PUT, new HttpEntity<Object>(request,
|
||||
createHeaders(vaultToken)), responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a resource by DELETEing from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
* Delete a resource by DELETEing from the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param vaultToken the {@link VaultToken}.
|
||||
@@ -216,79 +235,93 @@ public class VaultClient extends VaultAccessor {
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> deleteForEntity(String path, VaultToken vaultToken,
|
||||
Class<T> responseType) {
|
||||
public <T, S extends T> VaultResponseEntity<S> deleteForEntity(String path,
|
||||
VaultToken vaultToken, Class<T> responseType) {
|
||||
|
||||
return exchange(path, HttpMethod.DELETE, new HttpEntity<Object>(null, createHeaders(vaultToken)), responseType,
|
||||
null);
|
||||
return exchange(path, HttpMethod.DELETE, new HttpEntity<Object>(null,
|
||||
createHeaders(vaultToken)), responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns the
|
||||
* response as {@link VaultResponseEntity}. URI Template variables are using the given URI variables, if any.
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity
|
||||
* to the request, and returns the response as {@link VaultResponseEntity}. URI
|
||||
* Template variables are using the given URI variables, if any.
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param method the HTTP method (GET, POST, etc).
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}.
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may
|
||||
* be {@code null}.
|
||||
* @param responseType the type of the return value.
|
||||
* @param uriVariables the variables to expand in the template.
|
||||
* @return the response as entity.
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate,
|
||||
HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType,
|
||||
Map<String, ?> uriVariables) throws RestClientException {
|
||||
|
||||
Assert.hasText(pathTemplate, "Path template must not be null or empty");
|
||||
Assert.isTrue(!pathTemplate.startsWith("/"), "Path template must not start with a slash (/)");
|
||||
Assert.isTrue(!pathTemplate.startsWith("/"),
|
||||
"Path template must not start with a slash (/)");
|
||||
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables) : getEndpoint().createUri(pathTemplate);
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables)
|
||||
: getEndpoint().createUri(pathTemplate);
|
||||
|
||||
return exchange(uri, method, requestEntity, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given path template, writing the given request entity to the request, and returns
|
||||
* the response as {@link VaultResponseEntity}. The given {@link ParameterizedTypeReference} is used to pass generic
|
||||
* type information:
|
||||
* Execute the HTTP method to the given path template, writing the given request
|
||||
* entity to the request, and returns the response as {@link VaultResponseEntity}. The
|
||||
* given {@link ParameterizedTypeReference} is used to pass generic type information:
|
||||
*
|
||||
* <pre class="code">
|
||||
* ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {};
|
||||
* ResponseEntity<List<MyBean>> response = client.exchange("http://example.com", HttpMethod.GET, null, myBean, null);
|
||||
* ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {
|
||||
* };
|
||||
* ResponseEntity<List<MyBean>> response = client.exchange("http://example.com",
|
||||
* HttpMethod.GET, null, myBean, null);
|
||||
* </pre>
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param method the HTTP method (GET, POST, etc).
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}.
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may
|
||||
* be {@code null}.
|
||||
* @param responseType the type of the return value.
|
||||
* @param uriVariables the variables to expand in the template.
|
||||
* @return the response as entity.
|
||||
*/
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables)
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate,
|
||||
HttpMethod method, HttpEntity<?> requestEntity,
|
||||
ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables)
|
||||
throws RestClientException {
|
||||
|
||||
Assert.hasText(pathTemplate, "Path template must not be null or empty");
|
||||
Assert.isTrue(!pathTemplate.startsWith("/"), "Path template must not start with a slash (/)");
|
||||
Assert.isTrue(!pathTemplate.startsWith("/"),
|
||||
"Path template must not start with a slash (/)");
|
||||
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables) : getEndpoint().createUri(pathTemplate);
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables)
|
||||
: getEndpoint().createUri(pathTemplate);
|
||||
|
||||
return exchange(uri, method, requestEntity, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a {@link RestTemplateCallback}. Allows to interact with the underlying {@link RestTemplate} and benefit
|
||||
* from optional parameter expansion.
|
||||
* Executes a {@link RestTemplateCallback}. Allows to interact with the underlying
|
||||
* {@link RestTemplate} and benefit from optional parameter expansion.
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @param callback the request.
|
||||
* @return the {@link RestTemplateCallback} return value.
|
||||
*/
|
||||
public <T> T doWithRestTemplate(String pathTemplate, Map<String, ?> uriVariables, RestTemplateCallback<T> callback) {
|
||||
public <T> T doWithRestTemplate(String pathTemplate, Map<String, ?> uriVariables,
|
||||
RestTemplateCallback<T> callback) {
|
||||
|
||||
Assert.hasText(pathTemplate, "Path template must not be null or empty");
|
||||
Assert.isTrue(!pathTemplate.startsWith("/"), "Path template must not start with a slash (/)");
|
||||
Assert.isTrue(!pathTemplate.startsWith("/"),
|
||||
"Path template must not start with a slash (/)");
|
||||
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables) : getEndpoint().createUri(pathTemplate);
|
||||
URI uri = uriVariables != null ? buildUri(pathTemplate, uriVariables)
|
||||
: getEndpoint().createUri(pathTemplate);
|
||||
|
||||
return super.doWithRestTemplate(uri, callback);
|
||||
}
|
||||
@@ -301,8 +334,9 @@ public class VaultClient extends VaultAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Vault {@link URI} based on the given {@link VaultEndpoint} and {@code pathTemplate}. URI template
|
||||
* variables will be expanded using {@code uriVariables}.
|
||||
* Build the Vault {@link URI} based on the given {@link VaultEndpoint} and
|
||||
* {@code pathTemplate}. URI template variables will be expanded using
|
||||
* {@code uriVariables}.
|
||||
*
|
||||
* @param pathTemplate must not be empty or {@literal null}.
|
||||
* @param uriVariables must not be {@literal null}.
|
||||
@@ -313,7 +347,8 @@ public class VaultClient extends VaultAccessor {
|
||||
|
||||
Assert.hasText(pathTemplate, "Path must not be empty");
|
||||
|
||||
return getRestTemplate().getUriTemplateHandler().expand(getEndpoint().createUriString(pathTemplate), uriVariables);
|
||||
return getRestTemplate().getUriTemplateHandler().expand(
|
||||
getEndpoint().createUriString(pathTemplate), uriVariables);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,7 +390,8 @@ public class VaultClient extends VaultAccessor {
|
||||
return new HttpHeaders();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,15 @@ package org.springframework.vault.client;
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object that defines Vault connection coordinates.
|
||||
* <p>
|
||||
* A {@link VaultEndpoint} defines the hostname, TCP port and the protocol scheme (HTTP or HTTPS).
|
||||
* A {@link VaultEndpoint} defines the hostname, TCP port and the protocol scheme (HTTP or
|
||||
* HTTPS).
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -71,7 +72,8 @@ public class VaultEndpoint implements Serializable {
|
||||
/**
|
||||
* Create a {@link VaultEndpoint} given a {@link URI}.
|
||||
*
|
||||
* @param uri must contain hostname, port and scheme, must not be empty or {@literal null}.
|
||||
* @param uri must contain hostname, port and scheme, must not be empty or
|
||||
* {@literal null}.
|
||||
* @return a new {@link VaultEndpoint}.
|
||||
*/
|
||||
public static VaultEndpoint from(URI uri) {
|
||||
@@ -117,7 +119,8 @@ public class VaultEndpoint implements Serializable {
|
||||
*/
|
||||
public void setPort(int port) {
|
||||
|
||||
Assert.isTrue(port >= 1 && port <= 65535, "Port must be a valid port in the range between 1 and 65535");
|
||||
Assert.isTrue(port >= 1 && port <= 65535,
|
||||
"Port must be a valid port in the range between 1 and 65535");
|
||||
|
||||
this.port = port;
|
||||
}
|
||||
@@ -134,7 +137,8 @@ public class VaultEndpoint implements Serializable {
|
||||
*/
|
||||
public void setScheme(String scheme) {
|
||||
|
||||
Assert.isTrue("http".equals(scheme) || "https".equals(scheme), "Scheme must be http or https");
|
||||
Assert.isTrue("http".equals(scheme) || "https".equals(scheme),
|
||||
"Scheme must be http or https");
|
||||
|
||||
this.scheme = scheme;
|
||||
}
|
||||
@@ -159,7 +163,8 @@ public class VaultEndpoint implements Serializable {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
return String.format("%s://%s:%s/%s/%s", getScheme(), getHost(), getPort(), API_VERSION, path);
|
||||
return String.format("%s://%s:%s/%s/%s", getScheme(), getHost(), getPort(),
|
||||
API_VERSION, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,7 +35,8 @@ public class VaultException extends NestedRuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code NestedRuntimeException} with the specified detail message and nested exception.
|
||||
* Creates a {@code NestedRuntimeException} with the specified detail message and
|
||||
* nested exception.
|
||||
*
|
||||
* @param msg the detail message
|
||||
* @param cause the nested exception
|
||||
|
||||
@@ -20,8 +20,9 @@ import java.net.URI;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* Encapsulates the client response used in {@link VaultAccessor}. Consists of the body, status code the location and a
|
||||
* message. The {@code body} is empty for all non-successful results. This class is immutable.
|
||||
* Encapsulates the client response used in {@link VaultAccessor}. Consists of the body,
|
||||
* status code the location and a message. The {@code body} is empty for all
|
||||
* non-successful results. This class is immutable.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -78,8 +79,8 @@ public class VaultResponseEntity<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the message of this entity. {@literal null} for successful responses but provided usually when the response
|
||||
* yielded an error.
|
||||
* @return the message of this entity. {@literal null} for successful responses but
|
||||
* provided usually when the response yielded an error.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
|
||||
@@ -44,12 +44,14 @@ import org.springframework.vault.support.SslConfiguration;
|
||||
public abstract class AbstractVaultConfiguration {
|
||||
|
||||
/**
|
||||
* @return Vault endpoint coordinates for HTTP/HTTPS communication, must not be {@literal null}.
|
||||
* @return Vault endpoint coordinates for HTTP/HTTPS communication, must not be
|
||||
* {@literal null}.
|
||||
*/
|
||||
public abstract VaultEndpoint vaultEndpoint();
|
||||
|
||||
/**
|
||||
* Annotate with {@link Bean} in case you want to expose a {@link ClientAuthentication} instance to the
|
||||
* Annotate with {@link Bean} in case you want to expose a
|
||||
* {@link ClientAuthentication} instance to the
|
||||
* {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* @return the {@link ClientAuthentication} to use. Must not be {@literal null}.
|
||||
@@ -57,10 +59,11 @@ public abstract class AbstractVaultConfiguration {
|
||||
public abstract ClientAuthentication clientAuthentication();
|
||||
|
||||
/**
|
||||
* Create a {@link AsyncTaskExecutor} used by {@link LifecycleAwareSessionManager}. Annotate with {@link Bean} in case
|
||||
* you want to expose a {@link AsyncTaskExecutor} instance to the
|
||||
* {@link org.springframework.context.ApplicationContext}. This might be useful to supply managed executor instances
|
||||
* or {@link AsyncTaskExecutor}s using a queue/pooled threads.
|
||||
* Create a {@link AsyncTaskExecutor} used by {@link LifecycleAwareSessionManager}.
|
||||
* Annotate with {@link Bean} in case you want to expose a {@link AsyncTaskExecutor}
|
||||
* instance to the {@link org.springframework.context.ApplicationContext}. This might
|
||||
* be useful to supply managed executor instances or {@link AsyncTaskExecutor}s using
|
||||
* a queue/pooled threads.
|
||||
*
|
||||
* @return the {@link AsyncTaskExecutor} to use. Must not be {@literal null}.
|
||||
* @see AsyncTaskExecutor
|
||||
@@ -70,8 +73,9 @@ public abstract class AbstractVaultConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a {@link LifecycleAwareSessionManager} using {@link #clientAuthentication()} and {@link #vaultClient()}.
|
||||
* This {@link SessionManager} uses {@link #asyncTaskExecutor()}.
|
||||
* Construct a {@link LifecycleAwareSessionManager} using
|
||||
* {@link #clientAuthentication()} and {@link #vaultClient()}. This
|
||||
* {@link SessionManager} uses {@link #asyncTaskExecutor()}.
|
||||
*
|
||||
* @return the {@link SessionManager} for Vault session management.
|
||||
* @see SessionManager
|
||||
@@ -86,7 +90,8 @@ public abstract class AbstractVaultConfiguration {
|
||||
ClientAuthentication clientAuthentication = clientAuthentication();
|
||||
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
|
||||
|
||||
return new LifecycleAwareSessionManager(clientAuthentication, asyncTaskExecutor(), vaultClient());
|
||||
return new LifecycleAwareSessionManager(clientAuthentication,
|
||||
asyncTaskExecutor(), vaultClient());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,18 +112,21 @@ public abstract class AbstractVaultConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ClientFactoryWrapper} containing a {@link ClientHttpRequestFactory}.
|
||||
* {@link ClientHttpRequestFactory} is not exposed as root bean because {@link ClientHttpRequestFactory} is configured
|
||||
* with {@link ClientOptions} and {@link SslConfiguration} which are not necessarily applicable for the whole
|
||||
* Create a {@link ClientFactoryWrapper} containing a {@link ClientHttpRequestFactory}
|
||||
* . {@link ClientHttpRequestFactory} is not exposed as root bean because
|
||||
* {@link ClientHttpRequestFactory} is configured with {@link ClientOptions} and
|
||||
* {@link SslConfiguration} which are not necessarily applicable for the whole
|
||||
* application.
|
||||
*
|
||||
* @return the {@link ClientFactoryWrapper} to wrap a {@link ClientHttpRequestFactory} instance.
|
||||
* @return the {@link ClientFactoryWrapper} to wrap a {@link ClientHttpRequestFactory}
|
||||
* instance.
|
||||
* @see #clientOptions()
|
||||
* @see #sslConfiguration()
|
||||
*/
|
||||
@Bean
|
||||
public ClientFactoryWrapper clientHttpRequestFactoryWrapper() {
|
||||
return new ClientFactoryWrapper(ClientHttpRequestFactoryFactory.create(clientOptions(), sslConfiguration()));
|
||||
return new ClientFactoryWrapper(ClientHttpRequestFactoryFactory.create(
|
||||
clientOptions(), sslConfiguration()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,12 +136,14 @@ public abstract class AbstractVaultConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public VaultClient vaultClient() {
|
||||
return new VaultClient(clientHttpRequestFactoryWrapper().getClientHttpRequestFactory(), vaultEndpoint());
|
||||
return new VaultClient(clientHttpRequestFactoryWrapper()
|
||||
.getClientHttpRequestFactory(), vaultEndpoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link VaultClientFactory} to be used with {@link VaultTemplate}. Uses by default
|
||||
* {@link DefaultVaultClientFactory} with the configured {@link #vaultClient()} instance.
|
||||
* Creates the {@link VaultClientFactory} to be used with {@link VaultTemplate}. Uses
|
||||
* by default {@link DefaultVaultClientFactory} with the configured
|
||||
* {@link #vaultClient()} instance.
|
||||
*
|
||||
* @return the {@link VaultClientFactory}.
|
||||
*/
|
||||
|
||||
@@ -28,12 +28,16 @@ import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
@@ -43,42 +47,44 @@ import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import org.springframework.vault.support.ClientOptions;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
|
||||
/**
|
||||
* Factory for {@link ClientHttpRequestFactory} that supports Apache HTTP Components, OkHttp, Netty and the JDK HTTP
|
||||
* client (in that order). This factory configures a {@link ClientHttpRequestFactory} depending on the available
|
||||
* dependencies.
|
||||
* Factory for {@link ClientHttpRequestFactory} that supports Apache HTTP Components,
|
||||
* OkHttp, Netty and the JDK HTTP client (in that order). This factory configures a
|
||||
* {@link ClientHttpRequestFactory} depending on the available dependencies.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ClientHttpRequestFactoryFactory {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ClientHttpRequestFactoryFactory.class);
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(ClientHttpRequestFactoryFactory.class);
|
||||
|
||||
private static final boolean HTTP_COMPONENTS_PRESENT = ClassUtils.isPresent("org.apache.http.client.HttpClient",
|
||||
private static final boolean HTTP_COMPONENTS_PRESENT = ClassUtils.isPresent(
|
||||
"org.apache.http.client.HttpClient",
|
||||
ClientHttpRequestFactoryFactory.class.getClassLoader());
|
||||
|
||||
private static final boolean OKHTTP_PRESENT = ClassUtils.isPresent("com.squareup.okhttp.OkHttpClient",
|
||||
private static final boolean OKHTTP_PRESENT = ClassUtils.isPresent(
|
||||
"com.squareup.okhttp.OkHttpClient",
|
||||
ClientHttpRequestFactoryFactory.class.getClassLoader());
|
||||
|
||||
private static final boolean NETTY_PRESENT = ClassUtils.isPresent("io.netty.channel.nio.NioEventLoopGroup",
|
||||
private static final boolean NETTY_PRESENT = ClassUtils.isPresent(
|
||||
"io.netty.channel.nio.NioEventLoopGroup",
|
||||
ClientHttpRequestFactoryFactory.class.getClassLoader());
|
||||
|
||||
/**
|
||||
* Creates a {@link ClientHttpRequestFactory} for the given {@link ClientOptions} and {@link SslConfiguration}.
|
||||
* Creates a {@link ClientHttpRequestFactory} for the given {@link ClientOptions} and
|
||||
* {@link SslConfiguration}.
|
||||
*
|
||||
* @param options must not be {@literal null}
|
||||
* @param sslConfiguration must not be {@literal null}
|
||||
* @return a new {@link ClientHttpRequestFactory}. Lifecycle beans must be initialized after obtaining.
|
||||
* @return a new {@link ClientHttpRequestFactory}. Lifecycle beans must be initialized
|
||||
* after obtaining.
|
||||
*/
|
||||
public static ClientHttpRequestFactory create(ClientOptions options, SslConfiguration sslConfiguration) {
|
||||
public static ClientHttpRequestFactory create(ClientOptions options,
|
||||
SslConfiguration sslConfiguration) {
|
||||
|
||||
Assert.notNull(options, "ClientOptions must not be null");
|
||||
Assert.notNull(sslConfiguration, "SslConfiguration must not be null");
|
||||
@@ -97,9 +103,11 @@ public class ClientHttpRequestFactoryFactory {
|
||||
return Netty.usingNetty(options, sslConfiguration);
|
||||
}
|
||||
|
||||
} catch (GeneralSecurityException e) {
|
||||
}
|
||||
catch (GeneralSecurityException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
@@ -114,14 +122,13 @@ public class ClientHttpRequestFactoryFactory {
|
||||
private static SSLContext getSSLContext(SslConfiguration sslConfiguration)
|
||||
throws GeneralSecurityException, IOException {
|
||||
|
||||
KeyManager[] keyManagers = sslConfiguration.getKeyStore() != null
|
||||
? createKeyManagerFactory(sslConfiguration.getKeyStore(), sslConfiguration.getKeyStorePassword())
|
||||
.getKeyManagers()
|
||||
: null;
|
||||
KeyManager[] keyManagers = sslConfiguration.getKeyStore() != null ? createKeyManagerFactory(
|
||||
sslConfiguration.getKeyStore(), sslConfiguration.getKeyStorePassword())
|
||||
.getKeyManagers() : null;
|
||||
|
||||
TrustManager[] trustManagers = sslConfiguration.getTrustStore() != null
|
||||
? createTrustManagerFactory(sslConfiguration.getTrustStore(), sslConfiguration.getTrustStorePassword())
|
||||
.getTrustManagers()
|
||||
TrustManager[] trustManagers = sslConfiguration.getTrustStore() != null ? createTrustManagerFactory(
|
||||
sslConfiguration.getTrustStore(),
|
||||
sslConfiguration.getTrustStorePassword()).getTrustManagers()
|
||||
: null;
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
@@ -130,21 +137,24 @@ public class ClientHttpRequestFactoryFactory {
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
private static KeyManagerFactory createKeyManagerFactory(Resource keystoreFile, String storePassword)
|
||||
throws GeneralSecurityException, IOException {
|
||||
private static KeyManagerFactory createKeyManagerFactory(Resource keystoreFile,
|
||||
String storePassword) throws GeneralSecurityException, IOException {
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
|
||||
loadKeyStore(keystoreFile, storePassword, keyStore);
|
||||
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
keyManagerFactory.init(keyStore, StringUtils.hasText(storePassword) ? storePassword.toCharArray() : new char[0]);
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory
|
||||
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
keyManagerFactory.init(keyStore,
|
||||
StringUtils.hasText(storePassword) ? storePassword.toCharArray()
|
||||
: new char[0]);
|
||||
|
||||
return keyManagerFactory;
|
||||
}
|
||||
|
||||
private static TrustManagerFactory createTrustManagerFactory(Resource trustFile, String storePassword)
|
||||
throws GeneralSecurityException, IOException {
|
||||
private static TrustManagerFactory createTrustManagerFactory(Resource trustFile,
|
||||
String storePassword) throws GeneralSecurityException, IOException {
|
||||
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
|
||||
@@ -157,14 +167,18 @@ public class ClientHttpRequestFactoryFactory {
|
||||
return trustManagerFactory;
|
||||
}
|
||||
|
||||
private static void loadKeyStore(Resource keyStoreResource, String storePassword, KeyStore keyStore)
|
||||
throws IOException, NoSuchAlgorithmException, CertificateException {
|
||||
private static void loadKeyStore(Resource keyStoreResource, String storePassword,
|
||||
KeyStore keyStore) throws IOException, NoSuchAlgorithmException,
|
||||
CertificateException {
|
||||
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = keyStoreResource.getInputStream();
|
||||
keyStore.load(inputStream, StringUtils.hasText(storePassword) ? storePassword.toCharArray() : null);
|
||||
} finally {
|
||||
keyStore.load(inputStream,
|
||||
StringUtils.hasText(storePassword) ? storePassword.toCharArray()
|
||||
: null);
|
||||
}
|
||||
finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
@@ -172,7 +186,8 @@ public class ClientHttpRequestFactoryFactory {
|
||||
}
|
||||
|
||||
private static boolean hasSslConfiguration(SslConfiguration sslConfiguration) {
|
||||
return sslConfiguration.getTrustStore() != null || sslConfiguration.getKeyStore() != null;
|
||||
return sslConfiguration.getTrustStore() != null
|
||||
|| sslConfiguration.getKeyStore() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,15 +197,17 @@ public class ClientHttpRequestFactoryFactory {
|
||||
*/
|
||||
static class HttpComponents {
|
||||
|
||||
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options, SslConfiguration sslConfiguration)
|
||||
throws GeneralSecurityException, IOException {
|
||||
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options,
|
||||
SslConfiguration sslConfiguration) throws GeneralSecurityException,
|
||||
IOException {
|
||||
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
|
||||
SSLContext sslContext = getSSLContext(sslConfiguration);
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
|
||||
sslContext);
|
||||
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
|
||||
httpClientBuilder.setSSLContext(sslContext);
|
||||
}
|
||||
@@ -214,12 +231,14 @@ public class ClientHttpRequestFactoryFactory {
|
||||
*/
|
||||
static class OkHttp {
|
||||
|
||||
static ClientHttpRequestFactory usingOkHttp(ClientOptions options, SslConfiguration sslConfiguration)
|
||||
throws GeneralSecurityException, IOException {
|
||||
static ClientHttpRequestFactory usingOkHttp(ClientOptions options,
|
||||
SslConfiguration sslConfiguration) throws GeneralSecurityException,
|
||||
IOException {
|
||||
|
||||
final OkHttpClient okHttpClient = new OkHttpClient();
|
||||
|
||||
OkHttpClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory(okHttpClient) {
|
||||
OkHttpClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory(
|
||||
okHttpClient) {
|
||||
|
||||
@Override
|
||||
public void destroy() throws IOException {
|
||||
@@ -233,7 +252,8 @@ public class ClientHttpRequestFactoryFactory {
|
||||
};
|
||||
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
okHttpClient.setSslSocketFactory(getSSLContext(sslConfiguration).getSocketFactory());
|
||||
okHttpClient.setSslSocketFactory(getSSLContext(sslConfiguration)
|
||||
.getSocketFactory());
|
||||
}
|
||||
|
||||
requestFactory.setConnectTimeout(options.getConnectionTimeout());
|
||||
@@ -250,8 +270,9 @@ public class ClientHttpRequestFactoryFactory {
|
||||
*/
|
||||
static class Netty {
|
||||
|
||||
static ClientHttpRequestFactory usingNetty(ClientOptions options, SslConfiguration sslConfiguration)
|
||||
throws GeneralSecurityException, IOException {
|
||||
static ClientHttpRequestFactory usingNetty(ClientOptions options,
|
||||
SslConfiguration sslConfiguration) throws GeneralSecurityException,
|
||||
IOException {
|
||||
|
||||
final Netty4ClientHttpRequestFactory requestFactory = new Netty4ClientHttpRequestFactory();
|
||||
|
||||
@@ -261,16 +282,19 @@ public class ClientHttpRequestFactoryFactory {
|
||||
.forClient();
|
||||
|
||||
if (sslConfiguration.getTrustStore() != null) {
|
||||
sslContextBuilder.trustManager(
|
||||
createTrustManagerFactory(sslConfiguration.getTrustStore(), sslConfiguration.getTrustStorePassword()));
|
||||
sslContextBuilder.trustManager(createTrustManagerFactory(
|
||||
sslConfiguration.getTrustStore(),
|
||||
sslConfiguration.getTrustStorePassword()));
|
||||
}
|
||||
|
||||
if (sslConfiguration.getKeyStore() != null) {
|
||||
sslContextBuilder.keyManager(
|
||||
createKeyManagerFactory(sslConfiguration.getKeyStore(), sslConfiguration.getKeyStorePassword()));
|
||||
sslContextBuilder.keyManager(createKeyManagerFactory(
|
||||
sslConfiguration.getKeyStore(),
|
||||
sslConfiguration.getKeyStorePassword()));
|
||||
}
|
||||
|
||||
requestFactory.setSslContext(sslContextBuilder.sslProvider(SslProvider.JDK).build());
|
||||
requestFactory.setSslContext(sslContextBuilder.sslProvider(
|
||||
SslProvider.JDK).build());
|
||||
}
|
||||
|
||||
requestFactory.setConnectTimeout(options.getConnectionTimeout());
|
||||
|
||||
@@ -21,7 +21,8 @@ import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link VaultClientFactory}. Returns the provided {@link VaultClient}.
|
||||
* Default implementation of {@link VaultClientFactory}. Returns the provided
|
||||
* {@link VaultClient}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -30,7 +31,8 @@ public class DefaultVaultClientFactory implements VaultClientFactory {
|
||||
private final VaultClient vaultClient;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultVaultClientFactory} returning always the same {@link VaultClient}.
|
||||
* Creates a new {@link DefaultVaultClientFactory} returning always the same
|
||||
* {@link VaultClient}.
|
||||
*
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
*/
|
||||
@@ -42,8 +44,8 @@ public class DefaultVaultClientFactory implements VaultClientFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultVaultClientFactory} using a default {@link VaultClient} and {@link VaultEndpoint}. Will
|
||||
* use Vault at {@code https://localhost:8200} .
|
||||
* Creates a new {@link DefaultVaultClientFactory} using a default {@link VaultClient}
|
||||
* and {@link VaultEndpoint}. Will use Vault at {@code https://localhost:8200} .
|
||||
*
|
||||
* @see VaultClient
|
||||
* @see VaultEndpoint
|
||||
|
||||
@@ -21,20 +21,22 @@ import java.util.Map;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.vault.client.VaultAccessor.RestTemplateCallback;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.client.VaultAccessor.RestTemplateCallback;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of Vault operations, implemented by {@link VaultTemplate}. This is the main
|
||||
* entry point to interact with Vault in an authenticated and unauthenticated context with configured
|
||||
* {@link VaultClient} instances.
|
||||
* Interface that specifies a basic set of Vault operations, implemented by
|
||||
* {@link VaultTemplate}. This is the main entry point to interact with Vault in an
|
||||
* authenticated and unauthenticated context with configured {@link VaultClient}
|
||||
* instances.
|
||||
* <p>
|
||||
* {@link VaultOperations} resolves {@link VaultClient} instances and allows execution of callback methods on various
|
||||
* levels. Callbacks can execute requests within a {@link #doWithVault(SessionCallback) session}, the
|
||||
* {@link #doWithVault(ClientCallback) client (without requiring a session)} and a
|
||||
* {@link VaultOperations} resolves {@link VaultClient} instances and allows execution of
|
||||
* callback methods on various levels. Callbacks can execute requests within a
|
||||
* {@link #doWithVault(SessionCallback) session}, the {@link #doWithVault(ClientCallback)
|
||||
* client (without requiring a session)} and a
|
||||
* {@link #doWithRestTemplate(String, Map, RestTemplateCallback) low-level}
|
||||
* {@link org.springframework.web.client.RestTemplate} level.
|
||||
*
|
||||
@@ -65,7 +67,8 @@ public interface VaultOperations {
|
||||
VaultTransitOperations opsForTransit();
|
||||
|
||||
/**
|
||||
* Returns {@link VaultTransitOperations} if the transit backend is mounted on a different path than {@code transit}.
|
||||
* Returns {@link VaultTransitOperations} if the transit backend is mounted on a
|
||||
* different path than {@code transit}.
|
||||
*
|
||||
* @param path the mount path
|
||||
* @return the operations interface to interact with the Vault transit backend.
|
||||
@@ -78,7 +81,8 @@ public interface VaultOperations {
|
||||
VaultPkiOperations opsForPki();
|
||||
|
||||
/**
|
||||
* Returns {@link VaultPkiOperations} if the PKI backend is mounted on a different path than {@code pki}.
|
||||
* Returns {@link VaultPkiOperations} if the PKI backend is mounted on a different
|
||||
* path than {@code pki}.
|
||||
*
|
||||
* @param path the mount path
|
||||
* @return the operations interface to interact with the Vault PKI backend.
|
||||
@@ -86,8 +90,8 @@ public interface VaultOperations {
|
||||
VaultPkiOperations opsForPki(String path);
|
||||
|
||||
/**
|
||||
* Read from a secret backend. Reading data using this method is suitable for secret backends that do not require a
|
||||
* request body.
|
||||
* Read from a secret backend. Reading data using this method is suitable for secret
|
||||
* backends that do not require a request body.
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @return the data. May be {@literal null} if the path does not exist.
|
||||
@@ -95,8 +99,8 @@ public interface VaultOperations {
|
||||
VaultResponse read(String path);
|
||||
|
||||
/**
|
||||
* Read from a secret backend. Reading data using this method is suitable for secret backends that do not require a
|
||||
* request body.
|
||||
* Read from a secret backend. Reading data using this method is suitable for secret
|
||||
* backends that do not require a request body.
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
* @param responseType must not be {@literal null}.
|
||||
@@ -129,8 +133,8 @@ public interface VaultOperations {
|
||||
void delete(String path);
|
||||
|
||||
/**
|
||||
* Executes a Vault {@link ClientCallback}. Allows to interact with Vault using {@link VaultClient} without requiring
|
||||
* a session.
|
||||
* Executes a Vault {@link ClientCallback}. Allows to interact with Vault using
|
||||
* {@link VaultClient} without requiring a session.
|
||||
*
|
||||
* @param clientCallback the request.
|
||||
* @return the {@link ClientCallback} return value.
|
||||
@@ -138,7 +142,8 @@ public interface VaultOperations {
|
||||
<T> T doWithVault(ClientCallback<T> clientCallback);
|
||||
|
||||
/**
|
||||
* Executes a Vault {@link SessionCallback}. Allows to interact with Vault in an authenticated session.
|
||||
* Executes a Vault {@link SessionCallback}. Allows to interact with Vault in an
|
||||
* authenticated session.
|
||||
*
|
||||
* @param sessionCallback the request.
|
||||
* @return the {@link SessionCallback} return value.
|
||||
@@ -146,15 +151,19 @@ public interface VaultOperations {
|
||||
<T> T doWithVault(SessionCallback<T> sessionCallback);
|
||||
|
||||
/**
|
||||
* Executes {@link RestTemplateCallback}. Expands the {@code pathTemplate} to an {@link java.net.URI} and allows
|
||||
* low-level interaction with the underlying {@link org.springframework.web.client.RestTemplate}.
|
||||
* Executes {@link RestTemplateCallback}. Expands the {@code pathTemplate} to an
|
||||
* {@link java.net.URI} and allows low-level interaction with the underlying
|
||||
* {@link org.springframework.web.client.RestTemplate}.
|
||||
*
|
||||
* @param pathTemplate the path of the resource, e.g. {@code transit/{key}/foo}, must not be empty or {@literal null}.
|
||||
* @param variables the variables for expansion of the {@code pathTemplate}, must not be {@literal null}.
|
||||
* @param pathTemplate the path of the resource, e.g. {@code transit/ key}/foo}, must
|
||||
* not be empty or {@literal null}.
|
||||
* @param variables the variables for expansion of the {@code pathTemplate}, must not
|
||||
* be {@literal null}.
|
||||
* @param callback the request callback.
|
||||
* @return the {@link RestTemplateCallback} return value.
|
||||
*/
|
||||
<T> T doWithRestTemplate(String pathTemplate, Map<String, ?> variables, RestTemplateCallback<T> callback);
|
||||
<T> T doWithRestTemplate(String pathTemplate, Map<String, ?> variables,
|
||||
RestTemplateCallback<T> callback);
|
||||
|
||||
/**
|
||||
* A callback for executing arbitrary operations on the {@link VaultClient}.
|
||||
@@ -189,25 +198,28 @@ public interface VaultOperations {
|
||||
}
|
||||
|
||||
/**
|
||||
* An authenticated Vault session. {@link VaultSession} exposes request accessor methods to be executed in an
|
||||
* authenticated context.
|
||||
* An authenticated Vault session. {@link VaultSession} exposes request accessor
|
||||
* methods to be executed in an authenticated context.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface VaultSession {
|
||||
|
||||
/**
|
||||
* Retrieve a resource by GETting from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
* Retrieve a resource by GETting from the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> getForEntity(String path, Class<T> responseType);
|
||||
<T, S extends T> VaultResponseEntity<S> getForEntity(String path,
|
||||
Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Issue a POST request using the given object to the path, and returns the response as {@link VaultResponseEntity}.
|
||||
* Issue a POST request using the given object to the path, and returns the
|
||||
* response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param request the Object to be POSTed, may be {@code null}.
|
||||
@@ -215,11 +227,12 @@ public interface VaultOperations {
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> postForEntity(String path, Object request, Class<T> responseType);
|
||||
<T, S extends T> VaultResponseEntity<S> postForEntity(String path,
|
||||
Object request, Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Create a new resource by PUTting the given object to the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
* Create a new resource by PUTting the given object to the path, and returns the
|
||||
* response as {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param request the Object to be PUT.
|
||||
@@ -227,53 +240,62 @@ public interface VaultOperations {
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> putForEntity(String path, Object request, Class<T> responseType);
|
||||
<T, S extends T> VaultResponseEntity<S> putForEntity(String path, Object request,
|
||||
Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Delete a resource by DELETEing from the path, and returns the response as {@link VaultResponseEntity}.
|
||||
* Delete a resource by DELETEing from the path, and returns the response as
|
||||
* {@link VaultResponseEntity}.
|
||||
*
|
||||
* @param path the path.
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity.
|
||||
* @see VaultResponseEntity
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> deleteForEntity(String path, Class<T> responseType);
|
||||
<T, S extends T> VaultResponseEntity<S> deleteForEntity(String path,
|
||||
Class<T> responseType);
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns
|
||||
* the response as {@link VaultResponseEntity}.
|
||||
* Execute the HTTP method to the given URI template, writing the given request
|
||||
* entity to the request, and returns the response as {@link VaultResponseEntity}.
|
||||
* <p>
|
||||
* URI Template variables are using the given URI variables, if any.
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param method the HTTP method (GET, POST, etc).
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}.
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request,
|
||||
* may be {@code null}.
|
||||
* @param responseType the type of the return value.
|
||||
* @param uriVariables the variables to expand in the template.
|
||||
* @return the response as entity.
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables);
|
||||
<T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate,
|
||||
HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType,
|
||||
Map<String, ?> uriVariables);
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given path template, writing the given request entity to the request, and returns
|
||||
* the response as {@link VaultResponseEntity}. The given {@link ParameterizedTypeReference} is used to pass generic
|
||||
* type information:
|
||||
* Execute the HTTP method to the given path template, writing the given request
|
||||
* entity to the request, and returns the response as {@link VaultResponseEntity}.
|
||||
* The given {@link ParameterizedTypeReference} is used to pass generic type
|
||||
* information:
|
||||
*
|
||||
* <pre class="code">
|
||||
* ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {};
|
||||
* ResponseEntity<List<MyBean>> response = session.exchange("http://example.com", HttpMethod.GET, null, myBean,
|
||||
* null);
|
||||
* ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {
|
||||
* };
|
||||
* ResponseEntity<List<MyBean>> response = session.exchange("http://example.com",
|
||||
* HttpMethod.GET, null, myBean, null);
|
||||
* </pre>
|
||||
*
|
||||
* @param pathTemplate the path template.
|
||||
* @param method the HTTP method (GET, POST, etc).
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}.
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request,
|
||||
* may be {@code null}.
|
||||
* @param responseType the type of the return value.
|
||||
* @param uriVariables the variables to expand in the template.
|
||||
* @return the response as entity.
|
||||
*/
|
||||
<T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables);
|
||||
<T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate,
|
||||
HttpMethod method, HttpEntity<?> requestEntity,
|
||||
ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,27 +23,33 @@ import org.springframework.vault.support.VaultCertificateResponse;
|
||||
/**
|
||||
* Interface that specifies PKI backend-related operations.
|
||||
* <p>
|
||||
* The PKI secret backend for Vault generates X.509 certificates dynamically based on configured roles. This means
|
||||
* services can get certificates needed for both client and server authentication without going through the usual manual
|
||||
* process of generating a private key and CSR, submitting to a CA, and waiting for a verification and signing process
|
||||
* to complete. Vault's built-in authentication and authorization mechanisms provide the verification functionality.
|
||||
* The PKI secret backend for Vault generates X.509 certificates dynamically based on
|
||||
* configured roles. This means services can get certificates needed for both client and
|
||||
* server authentication without going through the usual manual process of generating a
|
||||
* private key and CSR, submitting to a CA, and waiting for a verification and signing
|
||||
* process to complete. Vault's built-in authentication and authorization mechanisms
|
||||
* provide the verification functionality.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see <a href=
|
||||
* "https://www.vaultproject.io/docs/secrets/pki/index.html">https://www.vaultproject.io/docs/secrets/pki/index.html</a>
|
||||
* "https://www.vaultproject.io/docs/secrets/pki/index.html">https://www.vaultproject.io/docs/secrets/pki/index.html</a>
|
||||
*/
|
||||
public interface VaultPkiOperations {
|
||||
|
||||
/**
|
||||
* Requests a certificate bundle (private key and certificate) from Vault's PKI backend given a {@code roleName} and
|
||||
* {@link VaultCertificateRequest}. The issuing CA certificate is returned as well, so that only the root CA need be
|
||||
* in a client's trust store. Certificates use DER format and are base64 encoded.
|
||||
* Requests a certificate bundle (private key and certificate) from Vault's PKI
|
||||
* backend given a {@code roleName} and {@link VaultCertificateRequest}. The issuing
|
||||
* CA certificate is returned as well, so that only the root CA need be in a client's
|
||||
* trust store. Certificates use DER format and are base64 encoded.
|
||||
*
|
||||
* @param roleName must not be empty or {@literal null}.
|
||||
* @param certificateRequest must not be {@literal null}.
|
||||
* @return the {@link VaultCertificateResponse} containing a {@link CertificateBundle}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/secrets/pki/index.html#pki-issue">POST /pki/issue/[role name]</a>
|
||||
* @return the {@link VaultCertificateResponse} containing a {@link CertificateBundle}
|
||||
* .
|
||||
* @see <a
|
||||
* href="https://www.vaultproject.io/docs/secrets/pki/index.html#pki-issue">POST
|
||||
* /pki/issue/[role name]</a>
|
||||
*/
|
||||
VaultCertificateResponse issueCertificate(String roleName, VaultCertificateRequest certificateRequest)
|
||||
throws VaultException;
|
||||
VaultCertificateResponse issueCertificate(String roleName,
|
||||
VaultCertificateRequest certificateRequest) throws VaultException;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@ public class VaultPkiTemplate implements VaultPkiOperations {
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* Create a new {@link VaultPkiTemplate} given {@link VaultPkiOperations} and the mount {@code path}.
|
||||
* Create a new {@link VaultPkiTemplate} given {@link VaultPkiOperations} and the
|
||||
* mount {@code path}.
|
||||
*
|
||||
* @param vaultOperations must not be {@literal null}.
|
||||
* @param path must not be empty or {@literal null}.
|
||||
@@ -52,8 +53,8 @@ public class VaultPkiTemplate implements VaultPkiOperations {
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultCertificateResponse issueCertificate(final String roleName, VaultCertificateRequest certificateRequest)
|
||||
throws VaultException {
|
||||
public VaultCertificateResponse issueCertificate(final String roleName,
|
||||
VaultCertificateRequest certificateRequest) throws VaultException {
|
||||
|
||||
Assert.hasText(roleName, "Role name must not be empty");
|
||||
Assert.notNull(certificateRequest, "Certificate request must not be null");
|
||||
@@ -62,11 +63,17 @@ public class VaultPkiTemplate implements VaultPkiOperations {
|
||||
request.put("common_name", certificateRequest.getCommonName());
|
||||
|
||||
if (!certificateRequest.getAltNames().isEmpty()) {
|
||||
request.put("alt_names", StringUtils.collectionToDelimitedString(certificateRequest.getAltNames(), ","));
|
||||
request.put(
|
||||
"alt_names",
|
||||
StringUtils.collectionToDelimitedString(
|
||||
certificateRequest.getAltNames(), ","));
|
||||
}
|
||||
|
||||
if (!certificateRequest.getIpSubjectAltNames().isEmpty()) {
|
||||
request.put("ip_sans", StringUtils.collectionToDelimitedString(certificateRequest.getIpSubjectAltNames(), ","));
|
||||
request.put(
|
||||
"ip_sans",
|
||||
StringUtils.collectionToDelimitedString(
|
||||
certificateRequest.getIpSubjectAltNames(), ","));
|
||||
}
|
||||
|
||||
if (certificateRequest.getTtl() != null) {
|
||||
@@ -82,9 +89,11 @@ public class VaultPkiTemplate implements VaultPkiOperations {
|
||||
VaultResponseEntity<VaultCertificateResponse> entity = vaultOperations
|
||||
.doWithVault(new VaultOperations.SessionCallback<VaultResponseEntity<VaultCertificateResponse>>() {
|
||||
@Override
|
||||
public VaultResponseEntity<VaultCertificateResponse> doWithVault(VaultOperations.VaultSession session) {
|
||||
public VaultResponseEntity<VaultCertificateResponse> doWithVault(
|
||||
VaultOperations.VaultSession session) {
|
||||
|
||||
return session.postForEntity(String.format("%s/issue/%s", path, roleName), request,
|
||||
return session.postForEntity(
|
||||
String.format("%s/issue/%s", path, roleName), request,
|
||||
VaultCertificateResponse.class);
|
||||
}
|
||||
});
|
||||
@@ -99,9 +108,11 @@ public class VaultPkiTemplate implements VaultPkiOperations {
|
||||
private static String buildExceptionMessage(VaultResponseEntity<?> response) {
|
||||
|
||||
if (StringUtils.hasText(response.getMessage())) {
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(), response.getUri(), response.getMessage());
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(),
|
||||
response.getUri(), response.getMessage());
|
||||
}
|
||||
|
||||
return String.format("Status %s URI %s", response.getStatusCode(), response.getUri());
|
||||
return String.format("Status %s URI %s", response.getStatusCode(),
|
||||
response.getUri());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ public interface VaultSysOperations {
|
||||
|
||||
/**
|
||||
* @return {@literal true} if Vault is initialized.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-init.html">GET /sys/init</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-init.html">GET
|
||||
* /sys/init</a>
|
||||
*/
|
||||
boolean isInitialized() throws VaultException;
|
||||
|
||||
@@ -42,14 +43,17 @@ public interface VaultSysOperations {
|
||||
*
|
||||
* @param vaultInitializationRequest must not be {@literal null}.
|
||||
* @return the {@link VaultInitializationResponse}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-init.html">PUT /sys/init</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-init.html">PUT
|
||||
* /sys/init</a>
|
||||
*/
|
||||
VaultInitializationResponse initialize(VaultInitializationRequest vaultInitializationRequest) throws VaultException;
|
||||
VaultInitializationResponse initialize(
|
||||
VaultInitializationRequest vaultInitializationRequest) throws VaultException;
|
||||
|
||||
/**
|
||||
* Seal vault.
|
||||
*
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-seal.html">PUT /sys/seal</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-seal.html">PUT
|
||||
* /sys/seal</a>
|
||||
*/
|
||||
void seal() throws VaultException;
|
||||
|
||||
@@ -58,13 +62,15 @@ public interface VaultSysOperations {
|
||||
*
|
||||
* @param keyShare must not be empty and not {@literal null}.
|
||||
* @return the {@link VaultUnsealStatus}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-unseal.html">PUT /sys/unseal</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-unseal.html">PUT
|
||||
* /sys/unseal</a>
|
||||
*/
|
||||
VaultUnsealStatus unseal(String keyShare) throws VaultException;
|
||||
|
||||
/**
|
||||
* @return the {@link VaultUnsealStatus}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-unseal.html">GET /sys/unseal</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-unseal.html">GET
|
||||
* /sys/unseal</a>
|
||||
*/
|
||||
VaultUnsealStatus getUnsealStatus() throws VaultException;
|
||||
|
||||
@@ -73,13 +79,15 @@ public interface VaultSysOperations {
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @param vaultMount must not be {@literal null}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-mounts.html">POST /sys/mounts/{mount}</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-mounts.html">POST
|
||||
* /sys/mounts/{mount}</a>
|
||||
*/
|
||||
void mount(String path, VaultMount vaultMount) throws VaultException;
|
||||
|
||||
/**
|
||||
* @return {@link Map} of all secret backend {@link VaultMount mounts}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-mounts.html">GET /sys/mounts/</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-mounts.html">GET
|
||||
* /sys/mounts/</a>
|
||||
*/
|
||||
Map<String, VaultMount> getMounts() throws VaultException;
|
||||
|
||||
@@ -87,7 +95,8 @@ public interface VaultSysOperations {
|
||||
* Unmounts the secret backend mount at {@code path}.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-mounts.html">DELETE /sys/mounts/{mount}</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-mounts.html">DELETE
|
||||
* /sys/mounts/{mount}</a>
|
||||
*/
|
||||
void unmount(String path) throws VaultException;
|
||||
|
||||
@@ -96,13 +105,15 @@ public interface VaultSysOperations {
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @param vaultMount must not be {@literal null}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-auth.html">POST /sys/auth/{mount}</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-auth.html">POST
|
||||
* /sys/auth/{mount}</a>
|
||||
*/
|
||||
void authMount(String path, VaultMount vaultMount) throws VaultException;
|
||||
|
||||
/**
|
||||
* @return {@link Map} of all auth backend {@link VaultMount mounts}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-auth.html">GET /sys/auth/</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-auth.html">GET
|
||||
* /sys/auth/</a>
|
||||
*/
|
||||
Map<String, VaultMount> getAuthMounts() throws VaultException;
|
||||
|
||||
@@ -110,7 +121,8 @@ public interface VaultSysOperations {
|
||||
* Unmounts the auth backend mount at {@code path}.
|
||||
*
|
||||
* @param path must not be empty or {@literal null}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-auth.html">DELETE /sys/auth/{mount}</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-auth.html">DELETE
|
||||
* /sys/auth/{mount}</a>
|
||||
*/
|
||||
void authUnmount(String path) throws VaultException;
|
||||
|
||||
@@ -118,7 +130,8 @@ public interface VaultSysOperations {
|
||||
* Returns the health status of Vault.
|
||||
*
|
||||
* @return the {@link VaultHealth}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-health.html">GET /sys/health</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/http/sys-health.html">GET
|
||||
* /sys/health</a>
|
||||
*/
|
||||
VaultHealth health() throws VaultException;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,13 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -43,14 +50,6 @@ import org.springframework.vault.support.VaultUnsealStatus;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link VaultSysOperations}.
|
||||
*
|
||||
@@ -90,7 +89,8 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
@Override
|
||||
public Boolean doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<Map<String, Boolean>> response = client.getForEntity("sys/init", Map.class);
|
||||
VaultResponseEntity<Map<String, Boolean>> response = client.getForEntity(
|
||||
"sys/init", Map.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody().get("initialized");
|
||||
@@ -102,25 +102,28 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaultInitializationResponse initialize(final VaultInitializationRequest vaultInitializationRequest) {
|
||||
public VaultInitializationResponse initialize(
|
||||
final VaultInitializationRequest vaultInitializationRequest) {
|
||||
|
||||
Assert.notNull(vaultInitializationRequest, "VaultInitialization must not be null");
|
||||
|
||||
return vaultOperations.doWithVault(new ClientCallback<VaultInitializationResponse>() {
|
||||
return vaultOperations
|
||||
.doWithVault(new ClientCallback<VaultInitializationResponse>() {
|
||||
|
||||
@Override
|
||||
public VaultInitializationResponse doWithVault(VaultClient client) {
|
||||
@Override
|
||||
public VaultInitializationResponse doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<VaultInitializationResponseImpl> response = client.putForEntity("sys/init",
|
||||
vaultInitializationRequest, VaultInitializationResponseImpl.class);
|
||||
VaultResponseEntity<VaultInitializationResponseImpl> response = client
|
||||
.putForEntity("sys/init", vaultInitializationRequest,
|
||||
VaultInitializationResponseImpl.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
}
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -136,8 +139,10 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
@Override
|
||||
public VaultUnsealStatus doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<VaultUnsealStatusImpl> response = client.putForEntity("sys/unseal",
|
||||
Collections.singletonMap("key", keyShare), VaultUnsealStatusImpl.class);
|
||||
VaultResponseEntity<VaultUnsealStatusImpl> response = client
|
||||
.putForEntity("sys/unseal",
|
||||
Collections.singletonMap("key", keyShare),
|
||||
VaultUnsealStatusImpl.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
@@ -176,7 +181,8 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authMount(final String path, final VaultMount vaultMount) throws VaultException {
|
||||
public void authMount(final String path, final VaultMount vaultMount)
|
||||
throws VaultException {
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
Assert.notNull(vaultMount, "VaultMount must not be null");
|
||||
@@ -199,16 +205,19 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
@Override
|
||||
public VaultHealth health() {
|
||||
return vaultOperations.doWithRestTemplate("sys/health", Collections.<String, Object> emptyMap(), HEALTH);
|
||||
return vaultOperations.doWithRestTemplate("sys/health",
|
||||
Collections.<String, Object>emptyMap(), HEALTH);
|
||||
}
|
||||
|
||||
private static String buildExceptionMessage(VaultResponseEntity<?> response) {
|
||||
|
||||
if (StringUtils.hasText(response.getMessage())) {
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(), response.getUri(), response.getMessage());
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(),
|
||||
response.getUri(), response.getMessage());
|
||||
}
|
||||
|
||||
return String.format("Status %s URI %s", response.getStatusCode(), response.getUri());
|
||||
return String.format("Status %s URI %s", response.getStatusCode(),
|
||||
response.getUri());
|
||||
}
|
||||
|
||||
private static class GetUnsealStatus implements ClientCallback<VaultUnsealStatus> {
|
||||
@@ -216,8 +225,8 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
@Override
|
||||
public VaultUnsealStatus doWithVault(VaultClient client) {
|
||||
|
||||
VaultResponseEntity<VaultUnsealStatusImpl> response = client.getForEntity("sys/seal-status",
|
||||
VaultUnsealStatusImpl.class);
|
||||
VaultResponseEntity<VaultUnsealStatusImpl> response = client.getForEntity(
|
||||
"sys/seal-status", VaultUnsealStatusImpl.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
@@ -232,7 +241,8 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
@Override
|
||||
public Void doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<Map> response = session.putForEntity("sys/seal", null, Map.class);
|
||||
VaultResponseEntity<Map> response = session.putForEntity("sys/seal", null,
|
||||
Map.class);
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
@@ -244,7 +254,8 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
private static class GetMounts implements SessionCallback<Map<String, VaultMount>> {
|
||||
|
||||
private static final ParameterizedTypeReference<VaultMountsResponse> MOUNT_TYPE_REF = new ParameterizedTypeReference<VaultMountsResponse>() {};
|
||||
private static final ParameterizedTypeReference<VaultMountsResponse> MOUNT_TYPE_REF = new ParameterizedTypeReference<VaultMountsResponse>() {
|
||||
};
|
||||
|
||||
private final String path;
|
||||
|
||||
@@ -255,8 +266,9 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
@Override
|
||||
public Map<String, VaultMount> doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultMountsResponse> response = session.exchange(path, HttpMethod.GET, null, MOUNT_TYPE_REF,
|
||||
Collections.<String, Object> emptyMap());
|
||||
VaultResponseEntity<VaultMountsResponse> response = session.exchange(path,
|
||||
HttpMethod.GET, null, MOUNT_TYPE_REF,
|
||||
Collections.<String, Object>emptyMap());
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
|
||||
@@ -272,7 +284,8 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
throw new VaultException(buildExceptionMessage(response));
|
||||
}
|
||||
|
||||
private static class VaultMountsResponse extends VaultResponseSupport<Map<String, VaultMount>> {
|
||||
private static class VaultMountsResponse extends
|
||||
VaultResponseSupport<Map<String, VaultMount>> {
|
||||
|
||||
private Map<String, VaultMount> topLevelMounts = new HashMap<String, VaultMount>();
|
||||
|
||||
@@ -304,22 +317,26 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
}
|
||||
|
||||
private static class Health implements VaultAccessor.RestTemplateCallback<VaultHealth> {
|
||||
private static class Health implements
|
||||
VaultAccessor.RestTemplateCallback<VaultHealth> {
|
||||
|
||||
@Override
|
||||
public VaultHealth doWithRestTemplate(URI uri, RestTemplate restTemplate) {
|
||||
|
||||
try {
|
||||
|
||||
ResponseEntity<VaultHealthImpl> healthResponse = restTemplate.exchange(uri, HttpMethod.GET, null,
|
||||
VaultHealthImpl.class);
|
||||
ResponseEntity<VaultHealthImpl> healthResponse = restTemplate.exchange(
|
||||
uri, HttpMethod.GET, null, VaultHealthImpl.class);
|
||||
return healthResponse.getBody();
|
||||
} catch (HttpStatusCodeException responseError) {
|
||||
}
|
||||
catch (HttpStatusCodeException responseError) {
|
||||
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
return mapper.readValue(responseError.getResponseBodyAsString(), VaultHealthImpl.class);
|
||||
} catch (Exception jsonError) {
|
||||
return mapper.readValue(responseError.getResponseBodyAsString(),
|
||||
VaultHealthImpl.class);
|
||||
}
|
||||
catch (Exception jsonError) {
|
||||
throw responseError;
|
||||
}
|
||||
}
|
||||
@@ -331,7 +348,8 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
private List<String> keys = new ArrayList<String>();
|
||||
|
||||
@JsonProperty("root_token") private String rootToken;
|
||||
@JsonProperty("root_token")
|
||||
private String rootToken;
|
||||
|
||||
public VaultToken getRootToken() {
|
||||
return VaultToken.of(rootToken);
|
||||
@@ -343,9 +361,11 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
private boolean sealed;
|
||||
|
||||
@JsonProperty("t") private int secretThreshold;
|
||||
@JsonProperty("t")
|
||||
private int secretThreshold;
|
||||
|
||||
@JsonProperty("n") private int secretShares;
|
||||
@JsonProperty("n")
|
||||
private int secretShares;
|
||||
|
||||
private int progress;
|
||||
}
|
||||
@@ -360,8 +380,10 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
private final int serverTimeUtc;
|
||||
private final String version;
|
||||
|
||||
private VaultHealthImpl(@JsonProperty("initialized") boolean initialized, @JsonProperty("sealed") boolean sealed,
|
||||
@JsonProperty("standby") boolean standby, @JsonProperty("server_time_utc") int serverTimeUtc,
|
||||
private VaultHealthImpl(@JsonProperty("initialized") boolean initialized,
|
||||
@JsonProperty("sealed") boolean sealed,
|
||||
@JsonProperty("standby") boolean standby,
|
||||
@JsonProperty("server_time_utc") int serverTimeUtc,
|
||||
@JsonProperty("version") String version) {
|
||||
|
||||
this.initialized = initialized;
|
||||
|
||||
@@ -33,16 +33,16 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.authentication.ClientAuthentication;
|
||||
import org.springframework.vault.authentication.SessionManager;
|
||||
import org.springframework.vault.authentication.SimpleSessionManager;
|
||||
import org.springframework.vault.client.VaultAccessor.RestTemplateCallback;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.client.VaultAccessor.RestTemplateCallback;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
|
||||
/**
|
||||
* This class encapsulates main Vault interaction. {@link VaultTemplate} will log into Vault on initialization and use
|
||||
* the token throughout the whole lifetime.
|
||||
* This class encapsulates main Vault interaction. {@link VaultTemplate} will log into
|
||||
* Vault on initialization and use the token throughout the whole lifetime.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see VaultClientFactory
|
||||
@@ -57,19 +57,22 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
private final boolean dedicatedSessionManager;
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultTemplate} without setting {@link VaultClientFactory} and {@link SessionManager}.
|
||||
* Creates a new {@link VaultTemplate} without setting {@link VaultClientFactory} and
|
||||
* {@link SessionManager}.
|
||||
*/
|
||||
public VaultTemplate() {
|
||||
this.dedicatedSessionManager = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultTemplate} with a {@link VaultClient} and {@link ClientAuthentication}.
|
||||
* Creates a new {@link VaultTemplate} with a {@link VaultClient} and
|
||||
* {@link ClientAuthentication}.
|
||||
*
|
||||
* @param vaultClient must not be {@literal null}.
|
||||
* @param clientAuthentication must not be {@literal null}.
|
||||
*/
|
||||
public VaultTemplate(VaultClient vaultClient, ClientAuthentication clientAuthentication) {
|
||||
public VaultTemplate(VaultClient vaultClient,
|
||||
ClientAuthentication clientAuthentication) {
|
||||
|
||||
Assert.notNull(vaultClient, "VaultClientFactory must not be null");
|
||||
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
|
||||
@@ -80,12 +83,14 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link VaultTemplate} with a {@link VaultClientFactory} and {@link SessionManager}.
|
||||
* Creates a new {@link VaultTemplate} with a {@link VaultClientFactory} and
|
||||
* {@link SessionManager}.
|
||||
*
|
||||
* @param vaultClientFactory must not be {@literal null}.
|
||||
* @param sessionManager must not be {@literal null}.
|
||||
*/
|
||||
public VaultTemplate(VaultClientFactory vaultClientFactory, SessionManager sessionManager) {
|
||||
public VaultTemplate(VaultClientFactory vaultClientFactory,
|
||||
SessionManager sessionManager) {
|
||||
|
||||
Assert.notNull(vaultClientFactory, "VaultClientFactory must not be null");
|
||||
Assert.notNull(sessionManager, "SessionManager must not be null");
|
||||
@@ -184,16 +189,19 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
|
||||
VaultClient vaultClient = vaultClientFactory.getVaultClient();
|
||||
|
||||
return sessionCallback.doWithVault(new DefaultVaultSession(sessionManager, vaultClient));
|
||||
return sessionCallback.doWithVault(new DefaultVaultSession(sessionManager,
|
||||
vaultClient));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T doWithRestTemplate(String pathTemplate, Map<String, ?> uriVariables, RestTemplateCallback<T> callback) {
|
||||
public <T> T doWithRestTemplate(String pathTemplate, Map<String, ?> uriVariables,
|
||||
RestTemplateCallback<T> callback) {
|
||||
|
||||
Assert.notNull(callback, "RestTemplateCallback must not be null!");
|
||||
Assert.state(vaultClientFactory != null, "VaultClientFactory must not be null");
|
||||
|
||||
return vaultClientFactory.getVaultClient().doWithRestTemplate(pathTemplate, uriVariables, callback);
|
||||
return vaultClientFactory.getVaultClient().doWithRestTemplate(pathTemplate,
|
||||
uriVariables, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -215,7 +223,8 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
@Override
|
||||
public VaultResponseSupport<T> doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultResponseSupport<T>> entity = session.exchange(path, HttpMethod.GET, null, ref, null);
|
||||
VaultResponseEntity<VaultResponseSupport<T>> entity = session.exchange(
|
||||
path, HttpMethod.GET, null, ref, null);
|
||||
|
||||
if (entity.isSuccessful() && entity.hasBody()) {
|
||||
return entity.getBody();
|
||||
@@ -235,7 +244,8 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
|
||||
Assert.hasText(path, "Path must not be empty");
|
||||
|
||||
VaultListResponse read = doRead(String.format("%s?list=true", path.endsWith("/") ? path : (path + "/")),
|
||||
VaultListResponse read = doRead(
|
||||
String.format("%s?list=true", path.endsWith("/") ? path : (path + "/")),
|
||||
VaultListResponse.class);
|
||||
if (read == null) {
|
||||
return Collections.emptyList();
|
||||
@@ -253,7 +263,8 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
|
||||
@Override
|
||||
public VaultResponse doWithVault(VaultSession session) {
|
||||
VaultResponseEntity<VaultResponse> entity = session.postForEntity(path, body, VaultResponse.class);
|
||||
VaultResponseEntity<VaultResponse> entity = session.postForEntity(path,
|
||||
body, VaultResponse.class);
|
||||
|
||||
if (entity.isSuccessful()) {
|
||||
if (entity.hasBody()) {
|
||||
@@ -276,7 +287,8 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
|
||||
@Override
|
||||
public VaultResponse doWithVault(VaultSession session) {
|
||||
VaultResponseEntity<VaultResponse> entity = session.deleteForEntity(path, VaultResponse.class);
|
||||
VaultResponseEntity<VaultResponse> entity = session.deleteForEntity(path,
|
||||
VaultResponse.class);
|
||||
|
||||
if (entity.isSuccessful()) {
|
||||
return null;
|
||||
@@ -287,7 +299,8 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
});
|
||||
}
|
||||
|
||||
private <T> ParameterizedTypeReference<VaultResponseSupport<T>> getTypeReference(final Class<T> responseType) {
|
||||
private <T> ParameterizedTypeReference<VaultResponseSupport<T>> getTypeReference(
|
||||
final Class<T> responseType) {
|
||||
final Type supportType = new ParameterizedType() {
|
||||
|
||||
@Override
|
||||
@@ -339,10 +352,12 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
private static String buildExceptionMessage(VaultResponseEntity<?> response) {
|
||||
|
||||
if (StringUtils.hasText(response.getMessage())) {
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(), response.getUri(), response.getMessage());
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(),
|
||||
response.getUri(), response.getMessage());
|
||||
}
|
||||
|
||||
return String.format("Status %s URI %s", response.getStatusCode(), response.getUri());
|
||||
return String.format("Status %s URI %s", response.getStatusCode(),
|
||||
response.getUri());
|
||||
}
|
||||
|
||||
private static class DefaultVaultSession implements VaultSession {
|
||||
@@ -357,56 +372,73 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path, Class<T> responseType) {
|
||||
return vaultClient.getForEntity(path, sessionManager.getSessionToken(), responseType);
|
||||
public <T, S extends T> VaultResponseEntity<S> getForEntity(String path,
|
||||
Class<T> responseType) {
|
||||
return vaultClient.getForEntity(path, sessionManager.getSessionToken(),
|
||||
responseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path, Object request, Class<T> responseType) {
|
||||
return vaultClient.putForEntity(path, sessionManager.getSessionToken(), request, responseType);
|
||||
public <T, S extends T> VaultResponseEntity<S> putForEntity(String path,
|
||||
Object request, Class<T> responseType) {
|
||||
return vaultClient.putForEntity(path, sessionManager.getSessionToken(),
|
||||
request, responseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path, Object request, Class<T> responseType) {
|
||||
return vaultClient.postForEntity(path, sessionManager.getSessionToken(), request, responseType);
|
||||
public <T, S extends T> VaultResponseEntity<S> postForEntity(String path,
|
||||
Object request, Class<T> responseType) {
|
||||
return vaultClient.postForEntity(path, sessionManager.getSessionToken(),
|
||||
request, responseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> deleteForEntity(String path, Class<T> responseType) {
|
||||
return vaultClient.deleteForEntity(path, sessionManager.getSessionToken(), responseType);
|
||||
public <T, S extends T> VaultResponseEntity<S> deleteForEntity(String path,
|
||||
Class<T> responseType) {
|
||||
return vaultClient.deleteForEntity(path, sessionManager.getSessionToken(),
|
||||
responseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate,
|
||||
HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType,
|
||||
Map<String, ?> uriVariables) {
|
||||
|
||||
HttpEntity<?> requestEntityToUse = getHttpEntity(requestEntity);
|
||||
return vaultClient.exchange(pathTemplate, method, requestEntityToUse, responseType, uriVariables);
|
||||
return vaultClient.exchange(pathTemplate, method, requestEntityToUse,
|
||||
responseType, uriVariables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate, HttpMethod method,
|
||||
HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) {
|
||||
public <T, S extends T> VaultResponseEntity<S> exchange(String pathTemplate,
|
||||
HttpMethod method, HttpEntity<?> requestEntity,
|
||||
ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) {
|
||||
|
||||
HttpEntity<?> requestEntityToUse = getHttpEntity(requestEntity);
|
||||
return vaultClient.exchange(pathTemplate, method, requestEntityToUse, responseType, uriVariables);
|
||||
return vaultClient.exchange(pathTemplate, method, requestEntityToUse,
|
||||
responseType, uriVariables);
|
||||
}
|
||||
|
||||
private HttpEntity<?> getHttpEntity(HttpEntity<?> requestEntity) {
|
||||
|
||||
HttpHeaders httpHeaders = VaultClient.createHeaders(sessionManager.getSessionToken());
|
||||
HttpHeaders httpHeaders = VaultClient.createHeaders(sessionManager
|
||||
.getSessionToken());
|
||||
HttpEntity<?> requestEntityToUse = requestEntity;
|
||||
|
||||
if (requestEntityToUse != null) {
|
||||
|
||||
httpHeaders.putAll(requestEntity.getHeaders());
|
||||
requestEntityToUse = new HttpEntity<Object>(requestEntityToUse.getBody(), httpHeaders);
|
||||
} else {
|
||||
requestEntityToUse = new HttpEntity<Object>(requestEntityToUse.getBody(),
|
||||
httpHeaders);
|
||||
}
|
||||
else {
|
||||
requestEntityToUse = new HttpEntity<Object>(httpHeaders);
|
||||
}
|
||||
return requestEntityToUse;
|
||||
}
|
||||
}
|
||||
|
||||
private static class VaultListResponse extends VaultResponseSupport<Map<String, Object>> {}
|
||||
private static class VaultListResponse extends
|
||||
VaultResponseSupport<Map<String, Object>> {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ public interface VaultTokenOperations {
|
||||
* Create a new token.
|
||||
*
|
||||
* @return a {@link VaultTokenResponse}
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST /auth/token/create</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST
|
||||
* /auth/token/create</a>
|
||||
*/
|
||||
VaultTokenResponse create() throws VaultException;
|
||||
|
||||
@@ -41,7 +42,8 @@ public interface VaultTokenOperations {
|
||||
*
|
||||
* @param request must not be {@literal null}.
|
||||
* @return a {@link VaultTokenResponse}
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST /auth/token/create</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST
|
||||
* /auth/token/create</a>
|
||||
*/
|
||||
VaultTokenResponse create(VaultTokenRequest request) throws VaultException;
|
||||
|
||||
@@ -49,7 +51,8 @@ public interface VaultTokenOperations {
|
||||
* Create a new orphan token.
|
||||
*
|
||||
* @return a {@link VaultTokenResponse}
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST /auth/token/create-orphan</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST
|
||||
* /auth/token/create-orphan</a>
|
||||
*/
|
||||
VaultTokenResponse createOrphan();
|
||||
|
||||
@@ -58,7 +61,8 @@ public interface VaultTokenOperations {
|
||||
*
|
||||
* @param request must not be {@literal null}.
|
||||
* @return a {@link VaultTokenResponse}
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST /auth/token/create-orphan</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST
|
||||
* /auth/token/create-orphan</a>
|
||||
*/
|
||||
VaultTokenResponse createOrphan(VaultTokenRequest request);
|
||||
|
||||
@@ -67,7 +71,8 @@ public interface VaultTokenOperations {
|
||||
*
|
||||
* @param vaultToken must not be {@literal null}.
|
||||
* @return a {@link VaultTokenResponse}
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST /auth/token/renew/{token}</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST
|
||||
* /auth/token/renew/{token}</a>
|
||||
*/
|
||||
VaultTokenResponse renew(VaultToken vaultToken);
|
||||
|
||||
@@ -75,7 +80,8 @@ public interface VaultTokenOperations {
|
||||
* Revoke a {@link VaultToken}.
|
||||
*
|
||||
* @param vaultToken must not be {@literal null}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST /auth/token/revoke/{token}</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST
|
||||
* /auth/token/revoke/{token}</a>
|
||||
*/
|
||||
void revoke(VaultToken vaultToken);
|
||||
|
||||
@@ -83,7 +89,8 @@ public interface VaultTokenOperations {
|
||||
* Revoke a {@link VaultToken} but not its child tokens.
|
||||
*
|
||||
* @param vaultToken must not be {@literal null}.
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST /auth/token/revoke-orphan/{token}</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">POST
|
||||
* /auth/token/revoke-orphan/{token}</a>
|
||||
*/
|
||||
void revokeOrphan(VaultToken vaultToken);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,8 @@ public class VaultTokenTemplate implements VaultTokenOperations {
|
||||
|
||||
Assert.notNull(request, "VaultTokenRequest must not be null");
|
||||
|
||||
return vaultOperations.doWithVault(new CreateToken("auth/token/create-orphan", request));
|
||||
return vaultOperations.doWithVault(new CreateToken("auth/token/create-orphan",
|
||||
request));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,7 +78,8 @@ public class VaultTokenTemplate implements VaultTokenOperations {
|
||||
|
||||
Assert.notNull(vaultToken, "VaultToken must not be null");
|
||||
|
||||
return vaultOperations.doWithVault(new RenewToken(String.format("auth/token/renew/%s", vaultToken.getToken())));
|
||||
return vaultOperations.doWithVault(new RenewToken(String.format(
|
||||
"auth/token/renew/%s", vaultToken.getToken())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,7 +87,8 @@ public class VaultTokenTemplate implements VaultTokenOperations {
|
||||
|
||||
Assert.notNull(vaultToken, "VaultToken must not be null");
|
||||
|
||||
vaultOperations.doWithVault(new RevokeToken(String.format("auth/token/revoke/%s", vaultToken.getToken())));
|
||||
vaultOperations.doWithVault(new RevokeToken(String.format("auth/token/revoke/%s",
|
||||
vaultToken.getToken())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,16 +96,19 @@ public class VaultTokenTemplate implements VaultTokenOperations {
|
||||
|
||||
Assert.notNull(vaultToken, "VaultToken must not be null");
|
||||
|
||||
vaultOperations.doWithVault(new RevokeToken(String.format("auth/token/revoke-orphan/%s", vaultToken.getToken())));
|
||||
vaultOperations.doWithVault(new RevokeToken(String.format(
|
||||
"auth/token/revoke-orphan/%s", vaultToken.getToken())));
|
||||
}
|
||||
|
||||
private static String buildExceptionMessage(VaultResponseEntity<?> response) {
|
||||
|
||||
if (StringUtils.hasText(response.getMessage())) {
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(), response.getUri(), response.getMessage());
|
||||
return String.format("Status %s URI %s: %s", response.getStatusCode(),
|
||||
response.getUri(), response.getMessage());
|
||||
}
|
||||
|
||||
return String.format("Status %s URI %s", response.getStatusCode(), response.getUri());
|
||||
return String.format("Status %s URI %s", response.getStatusCode(),
|
||||
response.getUri());
|
||||
}
|
||||
|
||||
private static class CreateToken implements SessionCallback<VaultTokenResponse> {
|
||||
@@ -119,7 +125,8 @@ public class VaultTokenTemplate implements VaultTokenOperations {
|
||||
@Override
|
||||
public VaultTokenResponse doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(path, request, VaultTokenResponse.class);
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(
|
||||
path, request, VaultTokenResponse.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
@@ -140,7 +147,8 @@ public class VaultTokenTemplate implements VaultTokenOperations {
|
||||
@Override
|
||||
public Void doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(path, null, VaultTokenResponse.class);
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(
|
||||
path, null, VaultTokenResponse.class);
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
return null;
|
||||
@@ -161,7 +169,8 @@ public class VaultTokenTemplate implements VaultTokenOperations {
|
||||
@Override
|
||||
public VaultTokenResponse doWithVault(VaultSession session) {
|
||||
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(path, null, VaultTokenResponse.class);
|
||||
VaultResponseEntity<VaultTokenResponse> response = session.postForEntity(
|
||||
path, null, VaultTokenResponse.class);
|
||||
|
||||
if (response.isSuccessful() && response.hasBody()) {
|
||||
return response.getBody();
|
||||
|
||||
@@ -15,16 +15,17 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import org.springframework.vault.support.VaultTransitContext;
|
||||
import org.springframework.vault.support.VaultTransitKey;
|
||||
import org.springframework.vault.support.VaultTransitKeyConfiguration;
|
||||
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
|
||||
import org.springframework.vault.support.VaultTransitContext;
|
||||
|
||||
/**
|
||||
* Interface that specifies operations using the {@code transit} backend.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see <a href="https://www.vaultproject.io/docs/secrets/transit/index.html">Transit Secret Backend</a>
|
||||
* @see <a href="https://www.vaultproject.io/docs/secrets/transit/index.html">Transit
|
||||
* Secret Backend</a>
|
||||
*/
|
||||
public interface VaultTransitOperations {
|
||||
|
||||
@@ -36,8 +37,9 @@ public interface VaultTransitOperations {
|
||||
void createKey(String keyName);
|
||||
|
||||
/**
|
||||
* Creates a new named encryption key given a {@code name} and {@link VaultTransitKeyCreationRequest}. The key options
|
||||
* set here cannot be changed after key creation.
|
||||
* Creates a new named encryption key given a {@code name} and
|
||||
* {@link VaultTransitKeyCreationRequest}. The key options set here cannot be changed
|
||||
* after key creation.
|
||||
*
|
||||
* @param keyName must not be empty or {@literal null}.
|
||||
* @param createKeyRequest must not be {@literal null}.
|
||||
@@ -61,16 +63,17 @@ public interface VaultTransitOperations {
|
||||
VaultTransitKey getKey(String keyName);
|
||||
|
||||
/**
|
||||
* Deletes a named encryption key. It will no longer be possible to decrypt any data encrypted with the named key.
|
||||
* Deletes a named encryption key. It will no longer be possible to decrypt any data
|
||||
* encrypted with the named key.
|
||||
*
|
||||
* @param keyName must not be empty or {@literal null}.
|
||||
*/
|
||||
void deleteKey(String keyName);
|
||||
|
||||
/**
|
||||
* Rotates the version of the named key. After rotation, new plaintext requests will be encrypted with the new version
|
||||
* of the key. To upgrade ciphertext to be encrypted with the latest version of the key, use
|
||||
* {@link #rewrap(String, String)}.
|
||||
* Rotates the version of the named key. After rotation, new plaintext requests will
|
||||
* be encrypted with the new version of the key. To upgrade ciphertext to be encrypted
|
||||
* with the latest version of the key, use {@link #rewrap(String, String)}.
|
||||
*
|
||||
* @param keyName must not be empty or {@literal null}.
|
||||
* @see #rewrap(String, String)
|
||||
@@ -116,8 +119,9 @@ public interface VaultTransitOperations {
|
||||
byte[] decrypt(String keyName, String ciphertext, VaultTransitContext transitRequest);
|
||||
|
||||
/**
|
||||
* Rewrap the provided ciphertext using the latest version of the named key. Because this never returns plaintext, it
|
||||
* is possible to delegate this functionality to untrusted users or scripts.
|
||||
* Rewrap the provided ciphertext using the latest version of the named key. Because
|
||||
* this never returns plaintext, it is possible to delegate this functionality to
|
||||
* untrusted users or scripts.
|
||||
*
|
||||
* @param keyName must not be empty or {@literal null}.
|
||||
* @param ciphertext must not be empty or {@literal null}.
|
||||
@@ -127,8 +131,9 @@ public interface VaultTransitOperations {
|
||||
String rewrap(String keyName, String ciphertext);
|
||||
|
||||
/**
|
||||
* Rewrap the provided ciphertext using the latest version of the named key. Because this never returns plaintext, it
|
||||
* is possible to delegate this functionality to untrusted users or scripts.
|
||||
* Rewrap the provided ciphertext using the latest version of the named key. Because
|
||||
* this never returns plaintext, it is possible to delegate this functionality to
|
||||
* untrusted users or scripts.
|
||||
*
|
||||
* @param keyName must not be empty or {@literal null}.
|
||||
* @param ciphertext must not be empty or {@literal null}.
|
||||
|
||||
@@ -18,17 +18,16 @@ package org.springframework.vault.core;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.vault.support.VaultTransitContext;
|
||||
import org.springframework.vault.support.VaultTransitKey;
|
||||
import org.springframework.vault.support.VaultTransitKeyConfiguration;
|
||||
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
|
||||
import org.springframework.vault.support.VaultTransitContext;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link VaultTransitOperations}.
|
||||
@@ -62,9 +61,11 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
public void createKey(String keyName, VaultTransitKeyCreationRequest createKeyRequest) {
|
||||
|
||||
Assert.hasText(keyName, "KeyName must not be empty");
|
||||
Assert.notNull(createKeyRequest, "VaultTransitKeyCreationRequest must not be empty");
|
||||
Assert.notNull(createKeyRequest,
|
||||
"VaultTransitKeyCreationRequest must not be empty");
|
||||
|
||||
vaultOperations.write(String.format("%s/keys/%s", path, keyName), createKeyRequest);
|
||||
vaultOperations.write(String.format("%s/keys/%s", path, keyName),
|
||||
createKeyRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,7 +74,8 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
Assert.hasText(keyName, "KeyName must not be empty");
|
||||
Assert.notNull(keyConfiguration, "VaultKeyConfiguration must not be empty");
|
||||
|
||||
vaultOperations.write(String.format("%s/keys/%s/config", path, keyName), keyConfiguration);
|
||||
vaultOperations.write(String.format("%s/keys/%s/config", path, keyName),
|
||||
keyConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,8 +83,8 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
|
||||
Assert.hasText(keyName, "KeyName must not be empty");
|
||||
|
||||
VaultResponseSupport<VaultTransitKeyImpl> result = vaultOperations.read(String.format("%s/keys/%s", path, keyName),
|
||||
VaultTransitKeyImpl.class);
|
||||
VaultResponseSupport<VaultTransitKeyImpl> result = vaultOperations.read(
|
||||
String.format("%s/keys/%s", path, keyName), VaultTransitKeyImpl.class);
|
||||
|
||||
if (result != null) {
|
||||
return result.getData();
|
||||
@@ -117,12 +119,14 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
|
||||
request.put("plaintext", Base64Utils.encodeToString(plaintext.getBytes()));
|
||||
|
||||
return (String) vaultOperations.write(String.format("%s/encrypt/%s", path, keyName), request).getData()
|
||||
return (String) vaultOperations
|
||||
.write(String.format("%s/encrypt/%s", path, keyName), request).getData()
|
||||
.get("ciphertext");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encrypt(String keyName, byte[] plaintext, VaultTransitContext transitRequest) {
|
||||
public String encrypt(String keyName, byte[] plaintext,
|
||||
VaultTransitContext transitRequest) {
|
||||
|
||||
Assert.hasText(keyName, "KeyName must not be empty");
|
||||
Assert.notNull(plaintext, "Plain text must not be null");
|
||||
@@ -135,7 +139,8 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
applyTransitOptions(transitRequest, request);
|
||||
}
|
||||
|
||||
return (String) vaultOperations.write(String.format("%s/encrypt/%s", path, keyName), request).getData()
|
||||
return (String) vaultOperations
|
||||
.write(String.format("%s/encrypt/%s", path, keyName), request).getData()
|
||||
.get("ciphertext");
|
||||
}
|
||||
|
||||
@@ -149,14 +154,16 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
|
||||
request.put("ciphertext", ciphertext);
|
||||
|
||||
String plaintext = (String) vaultOperations.write(String.format("%s/decrypt/%s", path, keyName), request).getData()
|
||||
String plaintext = (String) vaultOperations
|
||||
.write(String.format("%s/decrypt/%s", path, keyName), request).getData()
|
||||
.get("plaintext");
|
||||
|
||||
return new String(Base64Utils.decodeFromString(plaintext));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] decrypt(String keyName, String ciphertext, VaultTransitContext transitRequest) {
|
||||
public byte[] decrypt(String keyName, String ciphertext,
|
||||
VaultTransitContext transitRequest) {
|
||||
|
||||
Assert.hasText(keyName, "KeyName must not be empty");
|
||||
Assert.hasText(keyName, "Cipher text must not be empty");
|
||||
@@ -169,7 +176,8 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
applyTransitOptions(transitRequest, request);
|
||||
}
|
||||
|
||||
String plaintext = (String) vaultOperations.write(String.format("%s/decrypt/%s", path, keyName), request).getData()
|
||||
String plaintext = (String) vaultOperations
|
||||
.write(String.format("%s/decrypt/%s", path, keyName), request).getData()
|
||||
.get("plaintext");
|
||||
|
||||
return Base64Utils.decodeFromString(plaintext);
|
||||
@@ -184,12 +192,14 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
Map<String, String> request = new LinkedHashMap<String, String>();
|
||||
request.put("ciphertext", ciphertext);
|
||||
|
||||
return (String) vaultOperations.write(String.format("%s/rewrap/%s", path, keyName), request).getData()
|
||||
return (String) vaultOperations
|
||||
.write(String.format("%s/rewrap/%s", path, keyName), request).getData()
|
||||
.get("ciphertext");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rewrap(String keyName, String ciphertext, VaultTransitContext transitRequest) {
|
||||
public String rewrap(String keyName, String ciphertext,
|
||||
VaultTransitContext transitRequest) {
|
||||
|
||||
Assert.hasText(keyName, "KeyName must not be empty");
|
||||
Assert.hasText(ciphertext, "Cipher text must not be empty");
|
||||
@@ -202,14 +212,17 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
applyTransitOptions(transitRequest, request);
|
||||
}
|
||||
|
||||
return (String) vaultOperations.write(String.format("%s/rewrap/%s", path, keyName), request).getData()
|
||||
return (String) vaultOperations
|
||||
.write(String.format("%s/rewrap/%s", path, keyName), request).getData()
|
||||
.get("ciphertext");
|
||||
}
|
||||
|
||||
private void applyTransitOptions(VaultTransitContext transitRequest, Map<String, String> request) {
|
||||
private void applyTransitOptions(VaultTransitContext transitRequest,
|
||||
Map<String, String> request) {
|
||||
|
||||
if (transitRequest.getContext() != null) {
|
||||
request.put("context", Base64Utils.encodeToString(transitRequest.getContext()));
|
||||
request.put("context",
|
||||
Base64Utils.encodeToString(transitRequest.getContext()));
|
||||
}
|
||||
|
||||
if (transitRequest.getNonce() != null) {
|
||||
@@ -220,19 +233,24 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
@Data
|
||||
static class VaultTransitKeyImpl implements VaultTransitKey {
|
||||
|
||||
@JsonProperty("cipher_mode") private String cipherMode;
|
||||
@JsonProperty("cipher_mode")
|
||||
private String cipherMode;
|
||||
|
||||
@JsonProperty("type") private String type;
|
||||
@JsonProperty("type")
|
||||
private String type;
|
||||
|
||||
@JsonProperty("deletion_allowed") private boolean deletionAllowed;
|
||||
@JsonProperty("deletion_allowed")
|
||||
private boolean deletionAllowed;
|
||||
|
||||
private boolean derived;
|
||||
|
||||
private Map<String, Long> keys;
|
||||
|
||||
@JsonProperty("latest_version") private boolean latestVersion;
|
||||
@JsonProperty("latest_version")
|
||||
private boolean latestVersion;
|
||||
|
||||
@JsonProperty("min_decryption_version") private int minDecryptionVersion;
|
||||
@JsonProperty("min_decryption_version")
|
||||
private int minDecryptionVersion;
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -30,7 +31,8 @@ import org.springframework.vault.core.VaultTemplate;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
|
||||
/**
|
||||
* {@link PropertySource} that reads keys and values from a {@link VaultTemplate} and {@code path}.
|
||||
* {@link PropertySource} that reads keys and values from a {@link VaultTemplate} and
|
||||
* {@code path}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 3.1
|
||||
@@ -38,30 +40,35 @@ import org.springframework.vault.support.VaultResponse;
|
||||
*/
|
||||
public class VaultPropertySource extends EnumerablePropertySource<VaultOperations> {
|
||||
|
||||
protected final static Logger logger = LoggerFactory.getLogger(VaultPropertySource.class);
|
||||
protected final static Logger logger = LoggerFactory
|
||||
.getLogger(VaultPropertySource.class);
|
||||
|
||||
private final String path;
|
||||
private final Map<String, String> properties = new LinkedHashMap<String, String>();
|
||||
private final Object lock = new Object();
|
||||
|
||||
/**
|
||||
* Create a new {@link VaultPropertySource} given a {@link VaultTemplate} and {@code path} inside of Vault. This
|
||||
* property source loads properties upon construction.
|
||||
* Create a new {@link VaultPropertySource} given a {@link VaultTemplate} and
|
||||
* {@code path} inside of Vault. This property source loads properties upon
|
||||
* construction.
|
||||
*
|
||||
* @param vaultOperations must not be {@literal null}.
|
||||
* @param path the path inside Vault (e.g. {@code secret/myapp/myproperties}. Must not be empty or {@literal null}.
|
||||
* @param path the path inside Vault (e.g. {@code secret/myapp/myproperties}. Must not
|
||||
* be empty or {@literal null}.
|
||||
*/
|
||||
public VaultPropertySource(VaultOperations vaultOperations, String path) {
|
||||
this(path, vaultOperations, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link VaultPropertySource} given a {@code name}, {@link VaultTemplate} and {@code path} inside of
|
||||
* Vault. This property source loads properties upon construction.
|
||||
* Create a new {@link VaultPropertySource} given a {@code name},
|
||||
* {@link VaultTemplate} and {@code path} inside of Vault. This property source loads
|
||||
* properties upon construction.
|
||||
*
|
||||
* @param name name of the property source, must not be {@literal null}.
|
||||
* @param vaultOperations must not be {@literal null}.
|
||||
* @param path the path inside Vault (e.g. {@code secret/myapp/myproperties}. Must not be empty or {@literal null}.
|
||||
* @param path the path inside Vault (e.g. {@code secret/myapp/myproperties}. Must not
|
||||
* be empty or {@literal null}.
|
||||
*/
|
||||
public VaultPropertySource(String name, VaultOperations vaultOperations, String path) {
|
||||
|
||||
@@ -116,7 +123,8 @@ public class VaultPropertySource extends EnumerablePropertySource<VaultOperation
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method converting a {@code String/Object} map to a {@code String/String} map.
|
||||
* Utility method converting a {@code String/Object} map to a {@code String/String}
|
||||
* map.
|
||||
*
|
||||
* @param data the map
|
||||
* @return
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
* Spring Vault's environment abstraction consisting property source support.
|
||||
*/
|
||||
package org.springframework.vault.core.env;
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
* Vault core support.
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
* Spring support for <a href="https://vaultproject.io">Hashicorp Vault</a>.
|
||||
*/
|
||||
package org.springframework.vault;
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
package org.springframework.vault.support;
|
||||
|
||||
class Base64 {
|
||||
private Base64() {}
|
||||
private Base64() {
|
||||
}
|
||||
|
||||
public static byte[] decode(String in) {
|
||||
// Ignore trailing '=' padding and whitespace from the input.
|
||||
@@ -28,7 +29,8 @@ class Base64 {
|
||||
}
|
||||
}
|
||||
|
||||
// If the input includes whitespace, this output array will be longer than necessary.
|
||||
// If the input includes whitespace, this output array will be longer than
|
||||
// necessary.
|
||||
byte[] out = new byte[(int) (limit * 6L / 8L)];
|
||||
int outCount = 0;
|
||||
int inCount = 0;
|
||||
@@ -43,23 +45,29 @@ class Base64 {
|
||||
// A 65 0
|
||||
// Z 90 25 (ASCII - 65)
|
||||
bits = c - 65;
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
}
|
||||
else if (c >= 'a' && c <= 'z') {
|
||||
// char ASCII value
|
||||
// a 97 26
|
||||
// z 122 51 (ASCII - 71)
|
||||
bits = c - 71;
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
}
|
||||
else if (c >= '0' && c <= '9') {
|
||||
// char ASCII value
|
||||
// 0 48 52
|
||||
// 9 57 61 (ASCII + 4)
|
||||
bits = c + 4;
|
||||
} else if (c == '+' || c == '-') {
|
||||
}
|
||||
else if (c == '+' || c == '-') {
|
||||
bits = 62;
|
||||
} else if (c == '/' || c == '_') {
|
||||
}
|
||||
else if (c == '/' || c == '_') {
|
||||
bits = 63;
|
||||
} else if (c == '\n' || c == '\r' || c == ' ' || c == '\t') {
|
||||
}
|
||||
else if (c == '\n' || c == '\r' || c == ' ' || c == '\t') {
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -79,11 +87,13 @@ class Base64 {
|
||||
if (lastWordChars == 1) {
|
||||
// We read 1 char followed by "===". But 6 bits is a truncated byte! Fail.
|
||||
return null;
|
||||
} else if (lastWordChars == 2) {
|
||||
}
|
||||
else if (lastWordChars == 2) {
|
||||
// We read 2 chars followed by "==". Emit 1 byte with 8 of those 12 bits.
|
||||
word = word << 12;
|
||||
out[outCount++] = (byte) (word >> 16);
|
||||
} else if (lastWordChars == 3) {
|
||||
}
|
||||
else if (lastWordChars == 3) {
|
||||
// We read 3 chars, followed by "=". Emit 2 bytes for 16 of those 18 bits.
|
||||
word = word << 6;
|
||||
out[outCount++] = (byte) (word >> 16);
|
||||
|
||||
@@ -22,15 +22,16 @@ import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.spec.KeySpec;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Value object representing a certificate bundle consisting of a private key, the certificate and the issuer
|
||||
* certificate. Certificate and keys can be either DER or PEM encoded. DER-encoded certificates can be converted to a
|
||||
* {@link KeySpec} and {@link X509Certificate}.
|
||||
* Value object representing a certificate bundle consisting of a private key, the
|
||||
* certificate and the issuer certificate. Certificate and keys can be either DER or PEM
|
||||
* encoded. DER-encoded certificates can be converted to a {@link KeySpec} and
|
||||
* {@link X509Certificate}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see #getPrivateKeySpec()
|
||||
@@ -48,7 +49,8 @@ public class CertificateBundle {
|
||||
private final String privateKey;
|
||||
|
||||
private CertificateBundle(@JsonProperty("serial_number") String serialNumber,
|
||||
@JsonProperty("certificate") String certificate, @JsonProperty("issuing_ca") String issuingCaCertificate,
|
||||
@JsonProperty("certificate") String certificate,
|
||||
@JsonProperty("issuing_ca") String issuingCaCertificate,
|
||||
@JsonProperty("private_key") String privateKey) {
|
||||
|
||||
this.serialNumber = serialNumber;
|
||||
@@ -58,7 +60,8 @@ public class CertificateBundle {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link CertificateBundle} given a private key with certificates and the serial number.
|
||||
* Create a {@link CertificateBundle} given a private key with certificates and the
|
||||
* serial number.
|
||||
*
|
||||
* @param serialNumber must not be empty or {@literal null}.
|
||||
* @param certificate must not be empty or {@literal null}.
|
||||
@@ -66,15 +69,16 @@ public class CertificateBundle {
|
||||
* @param privateKey must not be empty or {@literal null}.
|
||||
* @return the {@link CertificateBundle}
|
||||
*/
|
||||
public static CertificateBundle of(String serialNumber, String certificate, String issuingCaCertificate,
|
||||
String privateKey) {
|
||||
public static CertificateBundle of(String serialNumber, String certificate,
|
||||
String issuingCaCertificate, String privateKey) {
|
||||
|
||||
Assert.hasText(serialNumber, "Serial number must not be empty");
|
||||
Assert.hasText(certificate, "Certificate must not be empty");
|
||||
Assert.hasText(issuingCaCertificate, "Issuing CA certificate must not be empty");
|
||||
Assert.hasText(privateKey, "Private key must not be empty");
|
||||
|
||||
return new CertificateBundle(serialNumber, certificate, issuingCaCertificate, privateKey);
|
||||
return new CertificateBundle(serialNumber, certificate, issuingCaCertificate,
|
||||
privateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,23 +110,26 @@ public class CertificateBundle {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the private key as {@link KeySpec}. Only supported if private key is DER-encoded.
|
||||
* Retrieve the private key as {@link KeySpec}. Only supported if private key is
|
||||
* DER-encoded.
|
||||
*
|
||||
* @return the private {@link KeySpec}. {@link java.security.KeyFactory} can generate a
|
||||
* {@link java.security.PrivateKey} from this {@link KeySpec}.
|
||||
* @return the private {@link KeySpec}. {@link java.security.KeyFactory} can generate
|
||||
* a {@link java.security.PrivateKey} from this {@link KeySpec}.
|
||||
*/
|
||||
public KeySpec getPrivateKeySpec() {
|
||||
|
||||
try {
|
||||
byte[] bytes = Base64.decode(getPrivateKey());
|
||||
return KeystoreUtil.getRSAKeySpec(bytes);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException("Cannot create KeySpec from private key", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the certificate as {@link X509Certificate}. Only supported if certificate is DER-encoded.
|
||||
* Retrieve the certificate as {@link X509Certificate}. Only supported if certificate
|
||||
* is DER-encoded.
|
||||
*
|
||||
* @return the {@link X509Certificate}.
|
||||
*/
|
||||
@@ -131,15 +138,18 @@ public class CertificateBundle {
|
||||
try {
|
||||
byte[] bytes = Base64.decode(getCertificate());
|
||||
return KeystoreUtil.getCertificate(bytes);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException("Cannot create Certificate from certificate", e);
|
||||
} catch (CertificateException e) {
|
||||
}
|
||||
catch (CertificateException e) {
|
||||
throw new VaultException("Cannot create Certificate from certificate", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the issuing CA certificate as {@link X509Certificate}. Only supported if certificate is DER-encoded.
|
||||
* Retrieve the issuing CA certificate as {@link X509Certificate}. Only supported if
|
||||
* certificate is DER-encoded.
|
||||
*
|
||||
* @return the issuing CA {@link X509Certificate}.
|
||||
*/
|
||||
@@ -148,16 +158,21 @@ public class CertificateBundle {
|
||||
try {
|
||||
byte[] bytes = Base64.decode(getIssuingCaCertificate());
|
||||
return KeystoreUtil.getCertificate(bytes);
|
||||
} catch (IOException e) {
|
||||
throw new VaultException("Cannot create Certificate from issuing CA certificate", e);
|
||||
} catch (CertificateException e) {
|
||||
throw new VaultException("Cannot create Certificate from issuing CA certificate", e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException(
|
||||
"Cannot create Certificate from issuing CA certificate", e);
|
||||
}
|
||||
catch (CertificateException e) {
|
||||
throw new VaultException(
|
||||
"Cannot create Certificate from issuing CA certificate", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link KeyStore} from this {@link CertificateBundle} containing the private key and certificate chain.
|
||||
* Only supported if certificate and private key are DER-encoded.
|
||||
* Create a {@link KeyStore} from this {@link CertificateBundle} containing the
|
||||
* private key and certificate chain. Only supported if certificate and private key
|
||||
* are DER-encoded.
|
||||
*
|
||||
* @param keyAlias the key alias to use.
|
||||
* @return the {@link KeyStore} containing the private key and certificate chain.
|
||||
@@ -167,11 +182,13 @@ public class CertificateBundle {
|
||||
Assert.hasText(keyAlias, "Key alias must not be empty");
|
||||
|
||||
try {
|
||||
return KeystoreUtil.createKeyStore(keyAlias, getPrivateKeySpec(), getX509Certificate(),
|
||||
getX509IssuerCertificate());
|
||||
} catch (GeneralSecurityException e) {
|
||||
return KeystoreUtil.createKeyStore(keyAlias, getPrivateKeySpec(),
|
||||
getX509Certificate(), getX509IssuerCertificate());
|
||||
}
|
||||
catch (GeneralSecurityException e) {
|
||||
throw new VaultException("Cannot create KeyStore", e);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException("Cannot create KeyStore", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,9 @@ public class ClientOptions {
|
||||
private final int readTimeout;
|
||||
|
||||
/**
|
||||
* Creates new {@link ClientOptions} with default timeouts of {@literal 5} {@link TimeUnit#SECONDS} connection timeout
|
||||
* and {@literal 15} {@link TimeUnit#SECONDS} read timeout.
|
||||
* Creates new {@link ClientOptions} with default timeouts of {@literal 5}
|
||||
* {@link TimeUnit#SECONDS} connection timeout and {@literal 15}
|
||||
* {@link TimeUnit#SECONDS} read timeout.
|
||||
*/
|
||||
public ClientOptions() {
|
||||
this((int) TimeUnit.SECONDS.toMillis(5), (int) TimeUnit.SECONDS.toMillis(15));
|
||||
@@ -45,8 +46,10 @@ public class ClientOptions {
|
||||
/**
|
||||
* Creates new {@link ClientOptions}.
|
||||
*
|
||||
* @param connectionTimeout connection timeout in {@link TimeUnit#MILLISECONDS}, must be greater {@literal 0}.
|
||||
* @param readTimeout read timeout in {@link TimeUnit#MILLISECONDS}, must be greater {@literal 0}.
|
||||
* @param connectionTimeout connection timeout in {@link TimeUnit#MILLISECONDS}, must
|
||||
* be greater {@literal 0}.
|
||||
* @param readTimeout read timeout in {@link TimeUnit#MILLISECONDS}, must be greater
|
||||
* {@literal 0}.
|
||||
*/
|
||||
public ClientOptions(int connectionTimeout, int readTimeout) {
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
|
||||
@@ -33,16 +33,16 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Keystore utility to create a {@link KeyStore} containing a {@link CertificateBundle} with the certificate chain and
|
||||
* its private key.
|
||||
* Keystore utility to create a {@link KeyStore} containing a {@link CertificateBundle}
|
||||
* with the certificate chain and its private key.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class KeystoreUtil {
|
||||
|
||||
/**
|
||||
* Creates a {@link KeyStore} containing the {@link KeySpec} and {@link X509Certificate certificates} using the given
|
||||
* {@code keyAlias}.
|
||||
* Creates a {@link KeyStore} containing the {@link KeySpec} and
|
||||
* {@link X509Certificate certificates} using the given {@code keyAlias}.
|
||||
*
|
||||
* @param keyAlias
|
||||
* @param certificates
|
||||
@@ -50,8 +50,8 @@ class KeystoreUtil {
|
||||
* @throws GeneralSecurityException
|
||||
* @throws IOException
|
||||
*/
|
||||
static KeyStore createKeyStore(String keyAlias, KeySpec privateKeySpec, X509Certificate... certificates)
|
||||
throws GeneralSecurityException, IOException {
|
||||
static KeyStore createKeyStore(String keyAlias, KeySpec privateKeySpec,
|
||||
X509Certificate... certificates) throws GeneralSecurityException, IOException {
|
||||
|
||||
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||
PrivateKey privateKey = kf.generatePrivate(privateKeySpec);
|
||||
@@ -67,7 +67,8 @@ class KeystoreUtil {
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
static X509Certificate getCertificate(byte[] source) throws CertificateException, IOException {
|
||||
static X509Certificate getCertificate(byte[] source) throws CertificateException,
|
||||
IOException {
|
||||
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
|
||||
@@ -95,8 +96,8 @@ class KeystoreUtil {
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
private static List<X509Certificate> getCertificates(CertificateFactory cf, byte[] source)
|
||||
throws CertificateException, IOException {
|
||||
private static List<X509Certificate> getCertificates(CertificateFactory cf,
|
||||
byte[] source) throws CertificateException, IOException {
|
||||
|
||||
List<X509Certificate> x509Certificates = new ArrayList<X509Certificate>();
|
||||
|
||||
@@ -162,19 +163,22 @@ class KeystoreUtil {
|
||||
BigInteger exp2 = parser.read().getInteger();
|
||||
BigInteger crtCoef = parser.read().getInteger();
|
||||
|
||||
return new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);
|
||||
return new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2,
|
||||
exp1, exp2, crtCoef);
|
||||
}
|
||||
|
||||
/**
|
||||
* A bare-minimum ASN.1 DER decoder, just having enough functions to decode PKCS#1 private keys. Especially, it
|
||||
* doesn't handle explicitly tagged types with an outer tag.
|
||||
* A bare-minimum ASN.1 DER decoder, just having enough functions to decode PKCS#1
|
||||
* private keys. Especially, it doesn't handle explicitly tagged types with an outer
|
||||
* tag.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* This parser can only handle one layer. To parse nested constructs, get a new parser for each layer using
|
||||
* <code>Asn1Object.getParser()</code>.
|
||||
* This parser can only handle one layer. To parse nested constructs, get a new parser
|
||||
* for each layer using <code>Asn1Object.getParser()</code>.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* There are many DER decoders in JRE but using them will tie this program to a specific JCE/JVM.
|
||||
* There are many DER decoders in JRE but using them will tie this program to a
|
||||
* specific JCE/JVM.
|
||||
*/
|
||||
private static class DerParser {
|
||||
|
||||
@@ -235,8 +239,8 @@ class KeystoreUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read next object. If it's constructed, the value holds encoded content and it should be parsed by a new parser
|
||||
* from <code>Asn1Object.getParser</code>.
|
||||
* Read next object. If it's constructed, the value holds encoded content and it
|
||||
* should be parsed by a new parser from <code>Asn1Object.getParser</code>.
|
||||
*
|
||||
* @return A object
|
||||
* @throws IOException
|
||||
@@ -246,7 +250,8 @@ class KeystoreUtil {
|
||||
int tag = in.read();
|
||||
|
||||
if (tag == -1) {
|
||||
throw new IllegalStateException("Invalid DER: stream too short, missing tag");
|
||||
throw new IllegalStateException(
|
||||
"Invalid DER: stream too short, missing tag");
|
||||
}
|
||||
|
||||
int length = getLength();
|
||||
@@ -254,22 +259,25 @@ class KeystoreUtil {
|
||||
byte[] value = new byte[length];
|
||||
int n = in.read(value);
|
||||
if (n < length) {
|
||||
throw new IllegalStateException("Invalid DER: stream too short, missing value");
|
||||
throw new IllegalStateException(
|
||||
"Invalid DER: stream too short, missing value");
|
||||
}
|
||||
|
||||
return new Asn1Object(tag, length, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the length of the field. Can only support length encoding up to 4 octets.
|
||||
* Decode the length of the field. Can only support length encoding up to 4
|
||||
* octets.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* In BER/DER encoding, length can be encoded in 2 forms,
|
||||
* <ul>
|
||||
* <li>Short form. One octet. Bit 8 has value "0" and bits 7-1 give the length.
|
||||
* <li>Long form. Two to 127 octets (only 4 is supported here). Bit 8 of first octet has value "1" and bits 7-1 give
|
||||
* the number of additional length octets. Second and following octets give the length, base 256, most significant
|
||||
* digit first.
|
||||
* <li>Long form. Two to 127 octets (only 4 is supported here). Bit 8 of first
|
||||
* octet has value "1" and bits 7-1 give the number of additional length octets.
|
||||
* Second and following octets give the length, base 256, most significant digit
|
||||
* first.
|
||||
* </ul>
|
||||
*
|
||||
* @return The length as integer
|
||||
@@ -291,7 +299,8 @@ class KeystoreUtil {
|
||||
|
||||
// We can't handle length longer than 4 bytes
|
||||
if (i >= 0xFF || num > 4) {
|
||||
throw new IllegalStateException("Invalid DER: length field too big (" + i + ")");
|
||||
throw new IllegalStateException("Invalid DER: length field too big (" + i
|
||||
+ ")");
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[num];
|
||||
@@ -315,7 +324,8 @@ class KeystoreUtil {
|
||||
private final int tag;
|
||||
|
||||
/**
|
||||
* Construct a ASN.1 TLV. The TLV could be either a constructed or primitive entity.
|
||||
* Construct a ASN.1 TLV. The TLV could be either a constructed or primitive
|
||||
* entity.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* The first byte in DER encoding is made of following fields,
|
||||
@@ -327,11 +337,12 @@ class KeystoreUtil {
|
||||
* | Class | CF | + Type |
|
||||
* -------------------------------------------------
|
||||
* </pre>
|
||||
*
|
||||
* <ul>
|
||||
* <li>Class: Universal, Application, Context or Private
|
||||
* <li>CF: Constructed flag. If 1, the field is constructed.
|
||||
* <li>Type: This is actually called tag in ASN.1. It indicates data type (Integer, String) or a construct
|
||||
* (sequence, choice, set).
|
||||
* <li>Type: This is actually called tag in ASN.1. It indicates data type
|
||||
* (Integer, String) or a construct (sequence, choice, set).
|
||||
* </ul>
|
||||
*
|
||||
* @param tag Tag or Identifier
|
||||
@@ -369,7 +380,8 @@ class KeystoreUtil {
|
||||
*/
|
||||
public DerParser getParser() throws IOException {
|
||||
if (!isConstructed()) {
|
||||
throw new IllegalStateException("Invalid DER: can't parse primitive entity");
|
||||
throw new IllegalStateException(
|
||||
"Invalid DER: can't parse primitive entity");
|
||||
}
|
||||
|
||||
return new DerParser(value);
|
||||
@@ -401,30 +413,30 @@ class KeystoreUtil {
|
||||
|
||||
switch (type) {
|
||||
|
||||
// Not all are ISO-8859-1 but it's the closest thing
|
||||
case DerParser.NUMERIC_STRING:
|
||||
case DerParser.PRINTABLE_STRING:
|
||||
case DerParser.VIDEOTEX_STRING:
|
||||
case DerParser.IA5_STRING:
|
||||
case DerParser.GRAPHIC_STRING:
|
||||
case DerParser.ISO646_STRING:
|
||||
case DerParser.GENERAL_STRING:
|
||||
encoding = "ISO-8859-1";
|
||||
break;
|
||||
// Not all are ISO-8859-1 but it's the closest thing
|
||||
case DerParser.NUMERIC_STRING:
|
||||
case DerParser.PRINTABLE_STRING:
|
||||
case DerParser.VIDEOTEX_STRING:
|
||||
case DerParser.IA5_STRING:
|
||||
case DerParser.GRAPHIC_STRING:
|
||||
case DerParser.ISO646_STRING:
|
||||
case DerParser.GENERAL_STRING:
|
||||
encoding = "ISO-8859-1";
|
||||
break;
|
||||
|
||||
case DerParser.BMP_STRING:
|
||||
encoding = "UTF-16BE";
|
||||
break;
|
||||
case DerParser.BMP_STRING:
|
||||
encoding = "UTF-16BE";
|
||||
break;
|
||||
|
||||
case DerParser.UTF8_STRING:
|
||||
encoding = "UTF-8";
|
||||
break;
|
||||
case DerParser.UTF8_STRING:
|
||||
encoding = "UTF-8";
|
||||
break;
|
||||
|
||||
case DerParser.UNIVERSAL_STRING:
|
||||
throw new IOException("Invalid DER: can't handle UCS-4 string");
|
||||
case DerParser.UNIVERSAL_STRING:
|
||||
throw new IOException("Invalid DER: can't handle UCS-4 string");
|
||||
|
||||
default:
|
||||
throw new IOException("Invalid DER: object is not a string");
|
||||
default:
|
||||
throw new IOException("Invalid DER: object is not a string");
|
||||
}
|
||||
|
||||
return new String(value, encoding);
|
||||
|
||||
@@ -21,9 +21,10 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* SSL configuration.
|
||||
* <p>
|
||||
* Provides configuration for a key store and trust store for TLS certificate verification. Key store and trust store
|
||||
* may be left unconfigured if the JDK trust store contains all necessary certificates to verify TLS certificates. The
|
||||
* key store is used for Client Certificate authentication.
|
||||
* Provides configuration for a key store and trust store for TLS certificate
|
||||
* verification. Key store and trust store may be left unconfigured if the JDK trust store
|
||||
* contains all necessary certificates to verify TLS certificates. The key store is used
|
||||
* for Client Certificate authentication.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see Resource
|
||||
@@ -35,7 +36,8 @@ public class SslConfiguration {
|
||||
/**
|
||||
* Default {@link SslConfiguration} without a KeyStore/TrustStore configured.
|
||||
*/
|
||||
public static final SslConfiguration NONE = new SslConfiguration(null, null, null, null);
|
||||
public static final SslConfiguration NONE = new SslConfiguration(null, null, null,
|
||||
null);
|
||||
|
||||
/**
|
||||
* Trust store that holds certificates and private keys.
|
||||
@@ -57,7 +59,8 @@ public class SslConfiguration {
|
||||
*/
|
||||
private final String trustStorePassword;
|
||||
|
||||
public SslConfiguration(Resource keyStore, String keyStorePassword, Resource trustStore, String trustStorePassword) {
|
||||
public SslConfiguration(Resource keyStore, String keyStorePassword,
|
||||
Resource trustStore, String trustStorePassword) {
|
||||
|
||||
this.keyStore = keyStore;
|
||||
this.keyStorePassword = keyStorePassword;
|
||||
@@ -68,15 +71,18 @@ public class SslConfiguration {
|
||||
/**
|
||||
* Creates a new {@link SslConfiguration} for the given trust store.
|
||||
*
|
||||
* @param trustStore resource pointing to an existing trust store, must not be {@literal null}.
|
||||
* @param trustStore resource pointing to an existing trust store, must not be
|
||||
* {@literal null}.
|
||||
* @param trustStorePassword may be {@literal null}.
|
||||
* @return the created {@link SslConfiguration}.
|
||||
* @see java.security.KeyStore
|
||||
*/
|
||||
public static SslConfiguration forTrustStore(Resource trustStore, String trustStorePassword) {
|
||||
public static SslConfiguration forTrustStore(Resource trustStore,
|
||||
String trustStorePassword) {
|
||||
|
||||
Assert.notNull(trustStore, "TrustStore must not be null");
|
||||
Assert.notNull(trustStore.exists(), String.format("TrustStore %s does not exist", trustStore));
|
||||
Assert.notNull(trustStore.exists(),
|
||||
String.format("TrustStore %s does not exist", trustStore));
|
||||
|
||||
return new SslConfiguration(null, null, trustStore, trustStorePassword);
|
||||
}
|
||||
@@ -84,7 +90,8 @@ public class SslConfiguration {
|
||||
/**
|
||||
* Creates a new {@link SslConfiguration} for the given key store.
|
||||
*
|
||||
* @param keyStore resource pointing to an existing key store, must not be {@literal null}.
|
||||
* @param keyStore resource pointing to an existing key store, must not be
|
||||
* {@literal null}.
|
||||
* @param keyStorePassword may be {@literal null}.
|
||||
* @return the created {@link SslConfiguration}.
|
||||
* @see java.security.KeyStore
|
||||
@@ -92,7 +99,8 @@ public class SslConfiguration {
|
||||
public static SslConfiguration forKeyStore(Resource keyStore, String keyStorePassword) {
|
||||
|
||||
Assert.notNull(keyStore, "KeyStore must not be null");
|
||||
Assert.notNull(keyStore.exists(), String.format("KeyStore %s does not exist", keyStore));
|
||||
Assert.notNull(keyStore.exists(),
|
||||
String.format("KeyStore %s does not exist", keyStore));
|
||||
|
||||
return new SslConfiguration(keyStore, keyStorePassword, null, null);
|
||||
}
|
||||
@@ -100,27 +108,33 @@ public class SslConfiguration {
|
||||
/**
|
||||
* Creates a new {@link SslConfiguration} for the given truststore.
|
||||
*
|
||||
* @param keyStore resource pointing to an existing keystore, must not be {@literal null}.
|
||||
* @param keyStore resource pointing to an existing keystore, must not be
|
||||
* {@literal null}.
|
||||
* @param keyStorePassword may be {@literal null}.
|
||||
* @param trustStore resource pointing to an existing trust store, must not be {@literal null}.
|
||||
* @param trustStore resource pointing to an existing trust store, must not be
|
||||
* {@literal null}.
|
||||
* @param trustStorePassword may be {@literal null}.
|
||||
* @return the created {@link SslConfiguration}.
|
||||
* @see java.security.KeyStore
|
||||
*/
|
||||
public SslConfiguration create(Resource keyStore, String keyStorePassword, Resource trustStore,
|
||||
String trustStorePassword) {
|
||||
public SslConfiguration create(Resource keyStore, String keyStorePassword,
|
||||
Resource trustStore, String trustStorePassword) {
|
||||
|
||||
Assert.notNull(keyStore, "KeyStore must not be null");
|
||||
Assert.notNull(keyStore.exists(), String.format("KeyStore %s does not exist", trustStore));
|
||||
Assert.notNull(keyStore.exists(),
|
||||
String.format("KeyStore %s does not exist", trustStore));
|
||||
|
||||
Assert.notNull(trustStore, "TrustStore must not be null");
|
||||
Assert.notNull(trustStore.exists(), String.format("TrustStore %s does not exist", trustStore));
|
||||
Assert.notNull(trustStore.exists(),
|
||||
String.format("TrustStore %s does not exist", trustStore));
|
||||
|
||||
return new SslConfiguration(keyStore, keyStorePassword, trustStore, trustStorePassword);
|
||||
return new SslConfiguration(keyStore, keyStorePassword, trustStore,
|
||||
trustStorePassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link java.security.KeyStore key store} resource or {@literal null} if not configured.
|
||||
* @return the {@link java.security.KeyStore key store} resource or {@literal null} if
|
||||
* not configured.
|
||||
*/
|
||||
public Resource getKeyStore() {
|
||||
return keyStore;
|
||||
@@ -134,7 +148,8 @@ public class SslConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link java.security.KeyStore key store} resource or {@literal null} if not configured.
|
||||
* @return the {@link java.security.KeyStore key store} resource or {@literal null} if
|
||||
* not configured.
|
||||
*/
|
||||
public Resource getTrustStore() {
|
||||
return trustStore;
|
||||
|
||||
@@ -49,12 +49,14 @@ public class VaultCertificateRequest {
|
||||
private final Integer ttl;
|
||||
|
||||
/**
|
||||
* If {@literal true}, the given common name will not be included in DNS or Email Subject Alternate Names (as
|
||||
* appropriate). Useful if the CN is not a hostname or email address, but is instead some human-readable identifier.
|
||||
* If {@literal true}, the given common name will not be included in DNS or Email
|
||||
* Subject Alternate Names (as appropriate). Useful if the CN is not a hostname or
|
||||
* email address, but is instead some human-readable identifier.
|
||||
*/
|
||||
private final boolean excludeCommonNameFromSubjectAltNames;
|
||||
|
||||
VaultCertificateRequest(String commonName, List<String> altNames, List<String> ipSubjectAltNames, Integer ttl,
|
||||
VaultCertificateRequest(String commonName, List<String> altNames,
|
||||
List<String> ipSubjectAltNames, Integer ttl,
|
||||
Boolean excludeCommonNameFromSubjectAltNames) {
|
||||
|
||||
this.commonName = commonName;
|
||||
@@ -110,7 +112,8 @@ public class VaultCertificateRequest {
|
||||
private Integer ttl;
|
||||
private Boolean excludeCommonNameFromSubjectAltNames;
|
||||
|
||||
VaultCertificateRequestBuilder() {}
|
||||
VaultCertificateRequestBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the common name.
|
||||
@@ -155,12 +158,14 @@ public class VaultCertificateRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure IP subject alternative names. Replaces previously configured IP subject alt names.
|
||||
* Configure IP subject alternative names. Replaces previously configured IP
|
||||
* subject alt names.
|
||||
*
|
||||
* @param ipSubjectAltNames must not be {@literal null}.
|
||||
* @return {@code this} {@link VaultCertificateRequestBuilder}.
|
||||
*/
|
||||
public VaultCertificateRequestBuilder ipSubjectAltNames(Iterable<String> ipSubjectAltNames) {
|
||||
public VaultCertificateRequestBuilder ipSubjectAltNames(
|
||||
Iterable<String> ipSubjectAltNames) {
|
||||
|
||||
Assert.notNull(ipSubjectAltNames, "IP subject alt names must not be null");
|
||||
|
||||
@@ -213,8 +218,9 @@ public class VaultCertificateRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude the given common name from DNS or Email Subject Alternate Names (as appropriate). Useful if
|
||||
* the CN is not a hostname or email address, but is instead some human-readable identifier.
|
||||
* Exclude the given common name from DNS or Email Subject Alternate Names (as
|
||||
* appropriate). Useful if the CN is not a hostname or email address, but is
|
||||
* instead some human-readable identifier.
|
||||
*
|
||||
* @return {@code this} {@link VaultCertificateRequestBuilder}.
|
||||
*/
|
||||
@@ -225,7 +231,8 @@ public class VaultCertificateRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link VaultCertificateRequest} instance. Requires {@link #commonName(String)} to be configured.
|
||||
* Build a new {@link VaultCertificateRequest} instance. Requires
|
||||
* {@link #commonName(String)} to be configured.
|
||||
*
|
||||
* @return a new {@link VaultCertificateRequest}.
|
||||
*/
|
||||
@@ -235,30 +242,33 @@ public class VaultCertificateRequest {
|
||||
|
||||
List<String> altNames;
|
||||
switch (this.altNames.size()) {
|
||||
case 0:
|
||||
altNames = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
altNames = java.util.Collections.singletonList(this.altNames.get(0));
|
||||
break;
|
||||
default:
|
||||
altNames = java.util.Collections.unmodifiableList(new ArrayList<String>(this.altNames));
|
||||
case 0:
|
||||
altNames = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
altNames = java.util.Collections.singletonList(this.altNames.get(0));
|
||||
break;
|
||||
default:
|
||||
altNames = java.util.Collections.unmodifiableList(new ArrayList<String>(
|
||||
this.altNames));
|
||||
}
|
||||
|
||||
List<String> ipSubjectAltNames;
|
||||
switch (this.ipSubjectAltNames.size()) {
|
||||
case 0:
|
||||
ipSubjectAltNames = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
ipSubjectAltNames = java.util.Collections.singletonList(this.ipSubjectAltNames.get(0));
|
||||
break;
|
||||
default:
|
||||
ipSubjectAltNames = java.util.Collections.unmodifiableList(new ArrayList<String>(this.ipSubjectAltNames));
|
||||
case 0:
|
||||
ipSubjectAltNames = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
ipSubjectAltNames = java.util.Collections
|
||||
.singletonList(this.ipSubjectAltNames.get(0));
|
||||
break;
|
||||
default:
|
||||
ipSubjectAltNames = java.util.Collections
|
||||
.unmodifiableList(new ArrayList<String>(this.ipSubjectAltNames));
|
||||
}
|
||||
|
||||
return new VaultCertificateRequest(commonName, altNames, ipSubjectAltNames, ttl,
|
||||
excludeCommonNameFromSubjectAltNames);
|
||||
return new VaultCertificateRequest(commonName, altNames, ipSubjectAltNames,
|
||||
ttl, excludeCommonNameFromSubjectAltNames);
|
||||
}
|
||||
|
||||
private static <E> List<E> toList(Iterable<E> iter) {
|
||||
|
||||
@@ -20,4 +20,5 @@ package org.springframework.vault.support;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class VaultCertificateResponse extends VaultResponseSupport<CertificateBundle> {}
|
||||
public class VaultCertificateResponse extends VaultResponseSupport<CertificateBundle> {
|
||||
}
|
||||
|
||||
@@ -25,19 +25,20 @@ package org.springframework.vault.support;
|
||||
public interface VaultHealth {
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the Vault instance is initialized, otherwise {@literal false}.
|
||||
* @return {@literal true} if the Vault instance is initialized, otherwise
|
||||
* {@literal false}.
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the Vault instance is sealed, otherwise {@literal false} if the Vault instance is
|
||||
* unsealed.
|
||||
* @return {@literal true} if the Vault instance is sealed, otherwise {@literal false}
|
||||
* if the Vault instance is unsealed.
|
||||
*/
|
||||
boolean isSealed();
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the Vault instance is in standby mode, otherwise {@literal false} if the Vault instance
|
||||
* is active.
|
||||
* @return {@literal true} if the Vault instance is in standby mode, otherwise
|
||||
* {@literal false} if the Vault instance is active.
|
||||
*/
|
||||
boolean isStandby();
|
||||
|
||||
|
||||
@@ -24,9 +24,11 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
*/
|
||||
public class VaultInitializationRequest {
|
||||
|
||||
@JsonProperty("secret_shares") private final int secretShares;
|
||||
@JsonProperty("secret_shares")
|
||||
private final int secretShares;
|
||||
|
||||
@JsonProperty("secret_threshold") private final int secretThreshold;
|
||||
@JsonProperty("secret_threshold")
|
||||
private final int secretThreshold;
|
||||
|
||||
private VaultInitializationRequest(int secretShares, int secretThreshold) {
|
||||
this.secretShares = secretShares;
|
||||
@@ -34,7 +36,8 @@ public class VaultInitializationRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@literal VaultInitializationRequest} given {@code secretShares} and {@code secretThreshold}.
|
||||
* Create a new {@literal VaultInitializationRequest} given {@code secretShares} and
|
||||
* {@code secretThreshold}.
|
||||
*
|
||||
* @param secretShares
|
||||
* @param secretThreshold
|
||||
|
||||
@@ -17,15 +17,15 @@ package org.springframework.vault.support;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to bind Vault HTTP Mount API requests/responses.
|
||||
* <p>
|
||||
* A {@link VaultMount} represents an auth or secret mount with its config details. Instances of this class are
|
||||
* immutable once constructed.
|
||||
* A {@link VaultMount} represents an auth or secret mount with its config details.
|
||||
* Instances of this class are immutable once constructed.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see #builder()
|
||||
@@ -47,7 +47,8 @@ public class VaultMount {
|
||||
*/
|
||||
private final Map<String, Object> config;
|
||||
|
||||
private VaultMount(@JsonProperty("type") String type, @JsonProperty("description") String description,
|
||||
private VaultMount(@JsonProperty("type") String type,
|
||||
@JsonProperty("description") String description,
|
||||
@JsonProperty("config") Map<String, Object> config) {
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
@@ -103,7 +104,8 @@ public class VaultMount {
|
||||
|
||||
private Map<String, Object> config;
|
||||
|
||||
VaultMountBuilder() {}
|
||||
VaultMountBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the backend type.
|
||||
@@ -142,7 +144,8 @@ public class VaultMount {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link VaultMount} instance. Requires {@link #type(String)} to be configured.
|
||||
* Build a new {@link VaultMount} instance. Requires {@link #type(String)} to be
|
||||
* configured.
|
||||
*
|
||||
* @return a new {@link VaultMount}.
|
||||
*/
|
||||
|
||||
@@ -29,4 +29,5 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = false)
|
||||
public class VaultResponse extends VaultResponseSupport<Map<String, Object>> {}
|
||||
public class VaultResponse extends VaultResponseSupport<Map<String, Object>> {
|
||||
}
|
||||
|
||||
@@ -37,13 +37,17 @@ public class VaultResponseSupport<T> {
|
||||
|
||||
private Map<String, String> metadata;
|
||||
|
||||
@JsonProperty("wrap_info") private Map<String, String> wrapInfo;
|
||||
@JsonProperty("wrap_info")
|
||||
private Map<String, String> wrapInfo;
|
||||
|
||||
@JsonProperty("lease_duration") private long leaseDuration;
|
||||
@JsonProperty("lease_duration")
|
||||
private long leaseDuration;
|
||||
|
||||
@JsonProperty("lease_id") private String leaseId;
|
||||
@JsonProperty("lease_id")
|
||||
private String leaseId;
|
||||
|
||||
@JsonProperty("request_id") private String requestId;
|
||||
@JsonProperty("request_id")
|
||||
private String requestId;
|
||||
|
||||
private boolean renewable;
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object for a Vault token.
|
||||
*
|
||||
|
||||
@@ -33,19 +33,24 @@ public class VaultTokenRequest {
|
||||
|
||||
private Map<String, String> meta;
|
||||
|
||||
@JsonProperty("no_parent") private Boolean noParent;
|
||||
@JsonProperty("no_parent")
|
||||
private Boolean noParent;
|
||||
|
||||
@JsonProperty("no_default_policy") private Boolean noDefaultPolicy;
|
||||
@JsonProperty("no_default_policy")
|
||||
private Boolean noDefaultPolicy;
|
||||
|
||||
private Boolean renewable;
|
||||
|
||||
private String ttl;
|
||||
|
||||
@JsonProperty("explicit_max_ttl") private String explicitMaxTtl;
|
||||
@JsonProperty("explicit_max_ttl")
|
||||
private String explicitMaxTtl;
|
||||
|
||||
@JsonProperty("display_name") private String displayName;
|
||||
@JsonProperty("display_name")
|
||||
private String displayName;
|
||||
|
||||
@JsonProperty("num_uses") private Integer numUses;
|
||||
@JsonProperty("num_uses")
|
||||
private Integer numUses;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
|
||||
@@ -60,12 +60,14 @@ public class VaultTransitContext {
|
||||
private byte[] context;
|
||||
private byte[] nonce;
|
||||
|
||||
VaultTransitRequestBuilder() {}
|
||||
VaultTransitRequestBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a key derivation context for the {@code transit} operation.
|
||||
*
|
||||
* @param context key derivation context, provided as a binary data. Must be provided if derivation is enabled.
|
||||
* @param context key derivation context, provided as a binary data. Must be
|
||||
* provided if derivation is enabled.
|
||||
* @return {@code this} {@link VaultTransitRequestBuilder}.
|
||||
*/
|
||||
public VaultTransitContext.VaultTransitRequestBuilder context(byte[] context) {
|
||||
@@ -74,11 +76,13 @@ public class VaultTransitContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the nonce value for a {@code transit} operation. Must be provided if convergent encryption is enabled
|
||||
* for this key and the key was generated with Vault 0.6.1. Not required for keys created in 0.6.2+.
|
||||
* Configure the nonce value for a {@code transit} operation. Must be provided if
|
||||
* convergent encryption is enabled for this key and the key was generated with
|
||||
* Vault 0.6.1. Not required for keys created in 0.6.2+.
|
||||
*
|
||||
* @param nonce value must be exactly 96 bits (12 bytes) long and the user must ensure that for any given context
|
||||
* (and thus, any given encryption key) this nonce value is never reused
|
||||
* @param nonce value must be exactly 96 bits (12 bytes) long and the user must
|
||||
* ensure that for any given context (and thus, any given encryption key) this
|
||||
* nonce value is never reused
|
||||
* @return {@code this} {@link VaultTransitRequestBuilder}.
|
||||
*/
|
||||
public VaultTransitContext.VaultTransitRequestBuilder nonce(byte[] nonce) {
|
||||
|
||||
@@ -25,7 +25,8 @@ import java.util.Map;
|
||||
public interface VaultTransitKey {
|
||||
|
||||
/**
|
||||
* @return {@literal true} if deletion of the key is allowed. Key deletion must be turned on to make keys deletable.
|
||||
* @return {@literal true} if deletion of the key is allowed. Key deletion must be
|
||||
* turned on to make keys deletable.
|
||||
*/
|
||||
boolean isDeletionAllowed();
|
||||
|
||||
|
||||
@@ -24,9 +24,11 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
*/
|
||||
public class VaultTransitKeyConfiguration {
|
||||
|
||||
@JsonProperty("deletion_allowed") private final Boolean deletionAllowed;
|
||||
@JsonProperty("deletion_allowed")
|
||||
private final Boolean deletionAllowed;
|
||||
|
||||
@JsonProperty("latest_version") private final Integer latestVersion;
|
||||
@JsonProperty("latest_version")
|
||||
private final Integer latestVersion;
|
||||
|
||||
private VaultTransitKeyConfiguration(Boolean deletionAllowed, Integer latestVersion) {
|
||||
this.deletionAllowed = deletionAllowed;
|
||||
@@ -62,7 +64,8 @@ public class VaultTransitKeyConfiguration {
|
||||
private Boolean deletionAllowed;
|
||||
private Integer latestVersion;
|
||||
|
||||
VaultTransitKeyConfigurationBuilder() {}
|
||||
VaultTransitKeyConfigurationBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether key deletion is allowed.
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Transit backend key creation request options.
|
||||
*
|
||||
@@ -28,11 +28,14 @@ public class VaultTransitKeyCreationRequest {
|
||||
|
||||
private final Boolean derived;
|
||||
|
||||
@JsonProperty("type") private final String type;
|
||||
@JsonProperty("type")
|
||||
private final String type;
|
||||
|
||||
@JsonProperty("convergent_encryption") private final Boolean convergentEncryption;
|
||||
@JsonProperty("convergent_encryption")
|
||||
private final Boolean convergentEncryption;
|
||||
|
||||
private VaultTransitKeyCreationRequest(Boolean derived, String type, Boolean convergentEncryption) {
|
||||
private VaultTransitKeyCreationRequest(Boolean derived, String type,
|
||||
Boolean convergentEncryption) {
|
||||
this.derived = derived;
|
||||
this.type = type;
|
||||
this.convergentEncryption = convergentEncryption;
|
||||
@@ -66,7 +69,8 @@ public class VaultTransitKeyCreationRequest {
|
||||
private String type = "aes256-gcm96";
|
||||
private Boolean convergentEncryption;
|
||||
|
||||
VaultTransitKeyCreationRequestBuilder() {}
|
||||
VaultTransitKeyCreationRequestBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure key derivation.
|
||||
@@ -85,8 +89,9 @@ public class VaultTransitKeyCreationRequest {
|
||||
/**
|
||||
* Configure key derivation.
|
||||
*
|
||||
* @param derived {@literal true} if key derivation MUST be used. If enabled, all encrypt/decrypt requests to this
|
||||
* named key must provide a context which is used for key derivation. Defaults to {@literal false}.
|
||||
* @param derived {@literal true} if key derivation MUST be used. If enabled, all
|
||||
* encrypt/decrypt requests to this named key must provide a context which is used
|
||||
* for key derivation. Defaults to {@literal false}.
|
||||
* @return {@code this} {@link VaultTransitKeyCreationRequestBuilder}.
|
||||
*/
|
||||
public VaultTransitKeyCreationRequestBuilder derived(boolean derived) {
|
||||
@@ -96,20 +101,22 @@ public class VaultTransitKeyCreationRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure convergent encryption where the same plaintext creates the same ciphertext. Requires
|
||||
* {@link #derived(boolean)} to be {@literal true}.
|
||||
* Configure convergent encryption where the same plaintext creates the same
|
||||
* ciphertext. Requires {@link #derived(boolean)} to be {@literal true}.
|
||||
*
|
||||
* @param convergentEncryption {@literal true} the same plaintext creates the same ciphertext. Defaults to
|
||||
* {@literal false}.
|
||||
* @param convergentEncryption {@literal true} the same plaintext creates the same
|
||||
* ciphertext. Defaults to {@literal false}.
|
||||
* @return {@code this} {@link VaultTransitKeyCreationRequestBuilder}.
|
||||
*/
|
||||
public VaultTransitKeyCreationRequestBuilder convergentEncryption(boolean convergentEncryption) {
|
||||
public VaultTransitKeyCreationRequestBuilder convergentEncryption(
|
||||
boolean convergentEncryption) {
|
||||
this.convergentEncryption = convergentEncryption;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new {@link VaultTransitKeyCreationRequest} instance. Requires {@link #type(String)} to be configured.
|
||||
* Build a new {@link VaultTransitKeyCreationRequest} instance. Requires
|
||||
* {@link #type(String)} to be configured.
|
||||
*
|
||||
* @return a new {@link VaultTransitKeyCreationRequest}.
|
||||
*/
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
*/
|
||||
package org.springframework.vault.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -31,8 +32,7 @@ import org.springframework.vault.core.VaultIntegrationTestConfiguration;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.vault.util.VaultRule;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration test for {@link VaultPropertySource}.
|
||||
@@ -52,7 +52,8 @@ public class VaultPropertySourceInBeanConfigurationIntegrationTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired ClientClass clientClass;
|
||||
@Autowired
|
||||
ClientClass clientClass;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
@@ -62,7 +63,8 @@ public class VaultPropertySourceInBeanConfigurationIntegrationTest {
|
||||
|
||||
VaultOperations vaultOperations = rule.prepare().getVaultOperations();
|
||||
|
||||
vaultOperations.write("secret/myapp", Collections.singletonMap("myapp", "myvalue"));
|
||||
vaultOperations.write("secret/myapp",
|
||||
Collections.singletonMap("myapp", "myvalue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,13 +15,12 @@
|
||||
*/
|
||||
package org.springframework.vault.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -32,6 +31,8 @@ import org.springframework.vault.core.VaultIntegrationTestConfiguration;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.vault.util.VaultRule;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration test for {@link VaultPropertySource}.
|
||||
*
|
||||
@@ -42,11 +43,15 @@ import org.springframework.vault.util.VaultRule;
|
||||
public class VaultPropertySourceIntegrationTests {
|
||||
|
||||
@VaultPropertySource({ "secret/myapp", "secret/myapp/profile" })
|
||||
static class Config extends VaultIntegrationTestConfiguration {}
|
||||
static class Config extends VaultIntegrationTestConfiguration {
|
||||
}
|
||||
|
||||
@Autowired Environment env;
|
||||
@Autowired ApplicationContext context;
|
||||
@Value("${myapp}") String myapp;
|
||||
@Autowired
|
||||
Environment env;
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
@Value("${myapp}")
|
||||
String myapp;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
@@ -56,8 +61,10 @@ public class VaultPropertySourceIntegrationTests {
|
||||
|
||||
VaultOperations vaultOperations = rule.prepare().getVaultOperations();
|
||||
|
||||
vaultOperations.write("secret/myapp", Collections.singletonMap("myapp", "myvalue"));
|
||||
vaultOperations.write("secret/myapp/profile", Collections.singletonMap("myprofile", "myprofilevalue"));
|
||||
vaultOperations.write("secret/myapp",
|
||||
Collections.singletonMap("myapp", "myvalue"));
|
||||
vaultOperations.write("secret/myapp/profile",
|
||||
Collections.singletonMap("myprofile", "myprofilevalue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,13 +15,12 @@
|
||||
*/
|
||||
package org.springframework.vault.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -32,6 +31,8 @@ import org.springframework.vault.core.VaultIntegrationTestConfiguration;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.vault.util.VaultRule;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration test for {@link VaultPropertySource} using multiple annotations.
|
||||
*
|
||||
@@ -41,12 +42,17 @@ import org.springframework.vault.util.VaultRule;
|
||||
@ContextConfiguration
|
||||
public class VaultPropertySourceMultipleIntegrationTests {
|
||||
|
||||
@VaultPropertySources({ @VaultPropertySource("secret/myapp/profile"), @VaultPropertySource("secret/myapp") })
|
||||
static class Config extends VaultIntegrationTestConfiguration {}
|
||||
@VaultPropertySources({ @VaultPropertySource("secret/myapp/profile"),
|
||||
@VaultPropertySource("secret/myapp") })
|
||||
static class Config extends VaultIntegrationTestConfiguration {
|
||||
}
|
||||
|
||||
@Autowired Environment env;
|
||||
@Autowired ApplicationContext context;
|
||||
@Value("${myapp}") String myapp;
|
||||
@Autowired
|
||||
Environment env;
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
@Value("${myapp}")
|
||||
String myapp;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
@@ -56,8 +62,10 @@ public class VaultPropertySourceMultipleIntegrationTests {
|
||||
|
||||
VaultOperations vaultOperations = rule.prepare().getVaultOperations();
|
||||
|
||||
vaultOperations.write("secret/myapp", Collections.singletonMap("myapp", "myvalue"));
|
||||
vaultOperations.write("secret/myapp/profile", Collections.singletonMap("myprofile", "myprofilevalue"));
|
||||
vaultOperations.write("secret/myapp",
|
||||
Collections.singletonMap("myapp", "myvalue"));
|
||||
vaultOperations.write("secret/myapp/profile",
|
||||
Collections.singletonMap("myprofile", "myprofilevalue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,13 +15,12 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultEndpoint;
|
||||
import org.springframework.vault.client.VaultException;
|
||||
@@ -31,6 +30,8 @@ import org.springframework.vault.util.IntegrationTestSupport;
|
||||
import org.springframework.vault.util.Settings;
|
||||
import org.springframework.vault.util.TestRestTemplateFactory;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link AppIdAuthentication}.
|
||||
*
|
||||
@@ -45,37 +46,42 @@ public class AppIdAuthenticationIntegrationTests extends IntegrationTestSupport
|
||||
prepare().mountAuth("app-id");
|
||||
}
|
||||
|
||||
prepare().getVaultOperations().doWithVault(new VaultOperations.SessionCallback<Object>() {
|
||||
prepare().getVaultOperations().doWithVault(
|
||||
new VaultOperations.SessionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object doWithVault(VaultOperations.VaultSession session) {
|
||||
@Override
|
||||
public Object doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
Map<String, String> appIdData = new HashMap<String, String>();
|
||||
appIdData.put("value", "dummy"); // policy
|
||||
appIdData.put("display_name", "this is my test application");
|
||||
Map<String, String> appIdData = new HashMap<String, String>();
|
||||
appIdData.put("value", "dummy"); // policy
|
||||
appIdData.put("display_name", "this is my test application");
|
||||
|
||||
session.postForEntity("auth/app-id/map/app-id/myapp", appIdData, Map.class);
|
||||
session.postForEntity("auth/app-id/map/app-id/myapp", appIdData,
|
||||
Map.class);
|
||||
|
||||
Map<String, String> userIdData = new HashMap<String, String>();
|
||||
userIdData.put("value", "myapp"); // name of the app-id
|
||||
userIdData.put("cidr_block", "0.0.0.0/0");
|
||||
Map<String, String> userIdData = new HashMap<String, String>();
|
||||
userIdData.put("value", "myapp"); // name of the app-id
|
||||
userIdData.put("cidr_block", "0.0.0.0/0");
|
||||
|
||||
session.postForEntity("auth/app-id/map/user-id/static-userid-value", userIdData, Map.class);
|
||||
session.postForEntity(
|
||||
"auth/app-id/map/user-id/static-userid-value",
|
||||
userIdData, Map.class);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLoginSuccessfully() throws Exception {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("myapp") //
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("myapp") //
|
||||
.userIdMechanism(new StaticUserId("static-userid-value")) //
|
||||
.build();
|
||||
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings.createSslConfiguration()),
|
||||
new VaultEndpoint());
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings
|
||||
.createSslConfiguration()), new VaultEndpoint());
|
||||
|
||||
AppIdAuthentication authentication = new AppIdAuthentication(options, vaultClient);
|
||||
VaultToken login = authentication.login();
|
||||
@@ -86,12 +92,13 @@ public class AppIdAuthenticationIntegrationTests extends IntegrationTestSupport
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("wrong") //
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("wrong") //
|
||||
.userIdMechanism(new StaticUserId("wrong")) //
|
||||
.build();
|
||||
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings.createSslConfiguration()),
|
||||
new VaultEndpoint());
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings
|
||||
.createSslConfiguration()), new VaultEndpoint());
|
||||
|
||||
new AppIdAuthentication(options, vaultClient).login();
|
||||
}
|
||||
|
||||
@@ -15,12 +15,9 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
@@ -30,6 +27,13 @@ import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AppIdAuthentication}.
|
||||
*
|
||||
@@ -51,18 +55,24 @@ public class AppIdAuthenticationUnitTests {
|
||||
@Test
|
||||
public void loginShouldObtainTokenWithStaticUserId() throws Exception {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("hello") //
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("hello") //
|
||||
.userIdMechanism(new StaticUserId("world")) //
|
||||
.build();
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/app-id/login")) //
|
||||
.andExpect(method(HttpMethod.POST)) //
|
||||
.andExpect(jsonPath("$.app_id").value("hello")) //
|
||||
.andExpect(jsonPath("$.user_id").value("world")) //
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/app-id/login"))
|
||||
//
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
//
|
||||
.andExpect(jsonPath("$.app_id").value("hello"))
|
||||
//
|
||||
.andExpect(jsonPath("$.user_id").value("world"))
|
||||
//
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}"));
|
||||
|
||||
AppIdAuthentication authentication = new AppIdAuthentication(options, vaultClient);
|
||||
AppIdAuthentication authentication = new AppIdAuthentication(options,
|
||||
vaultClient);
|
||||
|
||||
VaultToken login = authentication.login();
|
||||
assertThat(login).isInstanceOf(LoginToken.class);
|
||||
@@ -72,7 +82,8 @@ public class AppIdAuthenticationUnitTests {
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder().appId("hello") //
|
||||
AppIdAuthenticationOptions options = AppIdAuthenticationOptions.builder()
|
||||
.appId("hello") //
|
||||
.userIdMechanism(new StaticUserId("world")) //
|
||||
.build();
|
||||
|
||||
|
||||
@@ -15,23 +15,26 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.CoreMatchers.anyOf;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.core.VaultOperations;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.anyOf;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assume.assumeThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link AppRoleAuthentication}.
|
||||
*
|
||||
@@ -42,8 +45,10 @@ public class AppRoleAuthenticationIntegrationTests extends IntegrationTestSuppor
|
||||
@Before
|
||||
public void before() {
|
||||
|
||||
assumeThat(prepare().getVaultOperations().opsForSys().health().getVersion(),
|
||||
not(anyOf(nullValue(), equalTo(""), containsString("0.5"), containsString("0.6.1"))));
|
||||
assumeThat(
|
||||
prepare().getVaultOperations().opsForSys().health().getVersion(),
|
||||
not(anyOf(nullValue(), equalTo(""), containsString("0.5"),
|
||||
containsString("0.6.1"))));
|
||||
|
||||
if (!prepare().hasAuth("approle")) {
|
||||
prepare().mountAuth("approle");
|
||||
@@ -59,14 +64,16 @@ public class AppRoleAuthenticationIntegrationTests extends IntegrationTestSuppor
|
||||
withSecretId.put("bound_cidr_list", "0.0.0.0/0");
|
||||
withSecretId.put("bind_secret_id", "true");
|
||||
|
||||
session.postForEntity("auth/approle/role/with-secret-id", withSecretId, Map.class);
|
||||
session.postForEntity("auth/approle/role/with-secret-id", withSecretId,
|
||||
Map.class);
|
||||
|
||||
Map<String, String> noSecretIdRole = new HashMap<String, String>();
|
||||
noSecretIdRole.put("policies", "dummy"); // policy
|
||||
noSecretIdRole.put("bound_cidr_list", "0.0.0.0/0");
|
||||
noSecretIdRole.put("bind_secret_id", "false");
|
||||
|
||||
session.postForEntity("auth/approle/role/no-secret-id", noSecretIdRole, Map.class);
|
||||
session.postForEntity("auth/approle/role/no-secret-id", noSecretIdRole,
|
||||
Map.class);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -77,8 +84,10 @@ public class AppRoleAuthenticationIntegrationTests extends IntegrationTestSuppor
|
||||
public void shouldAuthenticateWithRoleIdOnly() {
|
||||
|
||||
String roleId = getRoleId("no-secret-id");
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder().roleId(roleId).build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options, prepare().getVaultClient());
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
|
||||
.roleId(roleId).build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options,
|
||||
prepare().getVaultClient());
|
||||
|
||||
assertThat(authentication.login()).isNotNull();
|
||||
}
|
||||
@@ -88,11 +97,13 @@ public class AppRoleAuthenticationIntegrationTests extends IntegrationTestSuppor
|
||||
|
||||
String roleId = getRoleId("with-secret-id");
|
||||
String secretId = (String) getVaultOperations()
|
||||
.write(String.format("auth/approle/role/%s/secret-id", "with-secret-id"), null).getData().get("secret_id");
|
||||
.write(String.format("auth/approle/role/%s/secret-id", "with-secret-id"),
|
||||
null).getData().get("secret_id");
|
||||
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder().roleId(roleId).secretId(secretId)
|
||||
.build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options, prepare().getVaultClient());
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
|
||||
.roleId(roleId).secretId(secretId).build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options,
|
||||
prepare().getVaultClient());
|
||||
|
||||
assertThat(authentication.login()).isNotNull();
|
||||
}
|
||||
@@ -102,8 +113,10 @@ public class AppRoleAuthenticationIntegrationTests extends IntegrationTestSuppor
|
||||
|
||||
String roleId = getRoleId("with-secret-id");
|
||||
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder().roleId(roleId).build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options, prepare().getVaultClient());
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
|
||||
.roleId(roleId).build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options,
|
||||
prepare().getVaultClient());
|
||||
|
||||
assertThat(authentication.login()).isNotNull();
|
||||
}
|
||||
@@ -113,9 +126,10 @@ public class AppRoleAuthenticationIntegrationTests extends IntegrationTestSuppor
|
||||
|
||||
String roleId = getRoleId("with-secret-id");
|
||||
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder().roleId(roleId)
|
||||
.secretId("this-is-a-wrong-secret-id").build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options, prepare().getVaultClient());
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
|
||||
.roleId(roleId).secretId("this-is-a-wrong-secret-id").build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options,
|
||||
prepare().getVaultClient());
|
||||
|
||||
assertThat(authentication.login()).isNotNull();
|
||||
}
|
||||
@@ -126,16 +140,19 @@ public class AppRoleAuthenticationIntegrationTests extends IntegrationTestSuppor
|
||||
String roleId = getRoleId("with-secret-id");
|
||||
final String secretId = "hello_world";
|
||||
|
||||
final VaultResponse customSecretIdResponse = getVaultOperations()
|
||||
.write("auth/approle/role/with-secret-id/custom-secret-id", Collections.singletonMap("secret_id", secretId));
|
||||
final VaultResponse customSecretIdResponse = getVaultOperations().write(
|
||||
"auth/approle/role/with-secret-id/custom-secret-id",
|
||||
Collections.singletonMap("secret_id", secretId));
|
||||
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder().roleId(roleId).secretId(secretId)
|
||||
.build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options, prepare().getVaultClient());
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
|
||||
.roleId(roleId).secretId(secretId).build();
|
||||
AppRoleAuthentication authentication = new AppRoleAuthentication(options,
|
||||
prepare().getVaultClient());
|
||||
|
||||
assertThat(authentication.login()).isNotNull();
|
||||
|
||||
getVaultOperations().write("auth/approle/role/with-secret-id/secret-id-accessor/destroy",
|
||||
getVaultOperations().write(
|
||||
"auth/approle/role/with-secret-id/secret-id-accessor/destroy",
|
||||
customSecretIdResponse.getData());
|
||||
}
|
||||
|
||||
@@ -144,7 +161,8 @@ public class AppRoleAuthenticationIntegrationTests extends IntegrationTestSuppor
|
||||
}
|
||||
|
||||
private String getRoleId(String roleName) {
|
||||
return (String) getVaultOperations().read(String.format("auth/approle/role/%s/role-id", roleName)).getData()
|
||||
return (String) getVaultOperations()
|
||||
.read(String.format("auth/approle/role/%s/role-id", roleName)).getData()
|
||||
.get("role_id");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,9 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
@@ -30,6 +27,13 @@ import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AppRoleAuthentication}.
|
||||
*
|
||||
@@ -51,16 +55,22 @@ public class AppRoleAuthenticationUnitTests {
|
||||
@Test
|
||||
public void loginShouldObtainToken() throws Exception {
|
||||
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder().roleId("hello") //
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
|
||||
.roleId("hello") //
|
||||
.secretId("world") //
|
||||
.build();
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/approle/login")) //
|
||||
.andExpect(method(HttpMethod.POST)) //
|
||||
.andExpect(jsonPath("$.role_id").value("hello")) //
|
||||
.andExpect(jsonPath("$.secret_id").value("world")) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}"));
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/approle/login"))
|
||||
//
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
//
|
||||
.andExpect(jsonPath("$.role_id").value("hello"))
|
||||
//
|
||||
.andExpect(jsonPath("$.secret_id").value("world"))
|
||||
//
|
||||
.andRespond(
|
||||
withSuccess().contentType(MediaType.APPLICATION_JSON).body(
|
||||
"{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}"));
|
||||
|
||||
AppRoleAuthentication sut = new AppRoleAuthentication(options, vaultClient);
|
||||
|
||||
@@ -73,15 +83,24 @@ public class AppRoleAuthenticationUnitTests {
|
||||
@Test
|
||||
public void loginShouldObtainTokenWithoutSecretId() throws Exception {
|
||||
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder().roleId("hello") //
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
|
||||
.roleId("hello") //
|
||||
.build();
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/approle/login")) //
|
||||
.andExpect(method(HttpMethod.POST)) //
|
||||
.andExpect(jsonPath("$.role_id").value("hello")) //
|
||||
.andExpect(jsonPath("$.secret_id").doesNotExist()) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\", \"lease_duration\": 10, \"renewable\": true}" + "}"));
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/approle/login"))
|
||||
//
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
//
|
||||
.andExpect(jsonPath("$.role_id").value("hello"))
|
||||
//
|
||||
.andExpect(jsonPath("$.secret_id").doesNotExist())
|
||||
//
|
||||
.andRespond(
|
||||
withSuccess()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{"
|
||||
+ "\"auth\":{\"client_token\":\"my-token\", \"lease_duration\": 10, \"renewable\": true}"
|
||||
+ "}"));
|
||||
|
||||
AppRoleAuthentication sut = new AppRoleAuthentication(options, vaultClient);
|
||||
|
||||
@@ -96,7 +115,8 @@ public class AppRoleAuthenticationUnitTests {
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder().roleId("hello") //
|
||||
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
|
||||
.roleId("hello") //
|
||||
.build();
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/approle/login")) //
|
||||
|
||||
@@ -15,15 +15,12 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
@@ -33,6 +30,13 @@ import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AwsEc2Authentication}.
|
||||
*
|
||||
@@ -54,25 +58,30 @@ public class AwsEc2AuthenticationUnitTests {
|
||||
@Test
|
||||
public void shouldObtainIdentityDocument() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
mockRest.expect(
|
||||
requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
.andExpect(method(HttpMethod.GET)) //
|
||||
.andRespond(withSuccess().body("Hello, world"));
|
||||
|
||||
AwsEc2Authentication authentication = new AwsEc2Authentication(vaultClient);
|
||||
|
||||
assertThat(authentication.getEc2Login()).containsEntry("pkcs7", "Hello, world").containsKey("nonce").hasSize(2);
|
||||
assertThat(authentication.getEc2Login()).containsEntry("pkcs7", "Hello, world")
|
||||
.containsKey("nonce").hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainRole() throws Exception {
|
||||
|
||||
AwsEc2AuthenticationOptions options = AwsEc2AuthenticationOptions.builder().role("ami").build();
|
||||
AwsEc2AuthenticationOptions options = AwsEc2AuthenticationOptions.builder()
|
||||
.role("ami").build();
|
||||
|
||||
mockRest.expect(requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
mockRest.expect(
|
||||
requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
.andExpect(method(HttpMethod.GET)) //
|
||||
.andRespond(withSuccess().body("Hello, world"));
|
||||
|
||||
AwsEc2Authentication authentication = new AwsEc2Authentication(options, vaultClient, vaultClient.getRestTemplate());
|
||||
AwsEc2Authentication authentication = new AwsEc2Authentication(options,
|
||||
vaultClient, vaultClient.getRestTemplate());
|
||||
|
||||
assertThat(authentication.getEc2Login()) //
|
||||
.containsEntry("pkcs7", "Hello, world") //
|
||||
@@ -83,11 +92,18 @@ public class AwsEc2AuthenticationUnitTests {
|
||||
@Test
|
||||
public void shouldLogin() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/aws-ec2/login")) //
|
||||
.andExpect(method(HttpMethod.POST)) //
|
||||
.andExpect(jsonPath("$.pkcs7").value("value")) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\", \"lease_duration\":20}" + "}"));
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/aws-ec2/login"))
|
||||
//
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
//
|
||||
.andExpect(jsonPath("$.pkcs7").value("value"))
|
||||
//
|
||||
.andRespond(
|
||||
withSuccess()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{"
|
||||
+ "\"auth\":{\"client_token\":\"my-token\", \"lease_duration\":20}"
|
||||
+ "}"));
|
||||
|
||||
AwsEc2Authentication authentication = new AwsEc2Authentication(vaultClient) {
|
||||
@Override
|
||||
@@ -107,7 +123,8 @@ public class AwsEc2AuthenticationUnitTests {
|
||||
@Test(expected = VaultException.class)
|
||||
public void loginShouldFailWhileObtainingIdentityDocument() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
mockRest.expect(
|
||||
requestTo("http://169.254.169.254/latest/dynamic/instance-identity/pkcs7")) //
|
||||
.andRespond(withServerError());
|
||||
|
||||
new AwsEc2Authentication(vaultClient).login();
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.vault.util.Settings.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
@@ -26,6 +23,7 @@ import java.util.Map;
|
||||
import org.assertj.core.util.Files;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
@@ -39,12 +37,17 @@ import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
import org.springframework.vault.util.Settings;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.vault.util.Settings.createSslConfiguration;
|
||||
import static org.springframework.vault.util.Settings.findWorkDir;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ClientCertificateAuthentication}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ClientCertificateAuthenticationIntegrationTests extends IntegrationTestSupport {
|
||||
public class ClientCertificateAuthenticationIntegrationTests extends
|
||||
IntegrationTestSupport {
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
@@ -53,43 +56,49 @@ public class ClientCertificateAuthenticationIntegrationTests extends Integration
|
||||
prepare().mountAuth("cert");
|
||||
}
|
||||
|
||||
prepare().getVaultOperations().doWithVault(new VaultOperations.SessionCallback<Object>() {
|
||||
@Override
|
||||
public Object doWithVault(VaultOperations.VaultSession session) {
|
||||
prepare().getVaultOperations().doWithVault(
|
||||
new VaultOperations.SessionCallback<Object>() {
|
||||
@Override
|
||||
public Object doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
File workDir = findWorkDir();
|
||||
File workDir = findWorkDir();
|
||||
|
||||
String certificate = Files.contentOf(new File(workDir, "ca/certs/client.cert.pem"),
|
||||
Charset.forName("US-ASCII"));
|
||||
String certificate = Files.contentOf(new File(workDir,
|
||||
"ca/certs/client.cert.pem"), Charset.forName("US-ASCII"));
|
||||
|
||||
session.postForEntity("auth/cert/certs/my-role", Collections.singletonMap("certificate", certificate),
|
||||
Map.class);
|
||||
session.postForEntity("auth/cert/certs/my-role",
|
||||
Collections.singletonMap("certificate", certificate),
|
||||
Map.class);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLoginSuccessfully() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory clientHttpRequestFactory = ClientHttpRequestFactoryFactory.create(new ClientOptions(),
|
||||
prepareCertAuthenticationMethod());
|
||||
VaultClient vaultClient = new VaultClient(clientHttpRequestFactory, new VaultEndpoint());
|
||||
ClientHttpRequestFactory clientHttpRequestFactory = ClientHttpRequestFactoryFactory
|
||||
.create(new ClientOptions(), prepareCertAuthenticationMethod());
|
||||
VaultClient vaultClient = new VaultClient(clientHttpRequestFactory,
|
||||
new VaultEndpoint());
|
||||
|
||||
ClientCertificateAuthentication authentication = new ClientCertificateAuthentication(vaultClient);
|
||||
ClientCertificateAuthentication authentication = new ClientCertificateAuthentication(
|
||||
vaultClient);
|
||||
VaultToken login = authentication.login();
|
||||
|
||||
assertThat(login.getToken()).isNotEmpty();
|
||||
}
|
||||
|
||||
// Compatibility for Vault 0.6.0 and below. Vault 0.6.1 fixed that issue and we receive a VaultException here.
|
||||
// Compatibility for Vault 0.6.0 and below. Vault 0.6.1 fixed that issue and we
|
||||
// receive a VaultException here.
|
||||
@Test(expected = NestedRuntimeException.class)
|
||||
public void loginShouldFail() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory clientHttpRequestFactory = ClientHttpRequestFactoryFactory.create(new ClientOptions(),
|
||||
Settings.createSslConfiguration());
|
||||
VaultClient vaultClient = new VaultClient(clientHttpRequestFactory, new VaultEndpoint());
|
||||
ClientHttpRequestFactory clientHttpRequestFactory = ClientHttpRequestFactoryFactory
|
||||
.create(new ClientOptions(), Settings.createSslConfiguration());
|
||||
VaultClient vaultClient = new VaultClient(clientHttpRequestFactory,
|
||||
new VaultEndpoint());
|
||||
|
||||
new ClientCertificateAuthentication(vaultClient).login();
|
||||
}
|
||||
@@ -98,9 +107,9 @@ public class ClientCertificateAuthenticationIntegrationTests extends Integration
|
||||
|
||||
SslConfiguration original = createSslConfiguration();
|
||||
|
||||
SslConfiguration sslConfiguration = new SslConfiguration(
|
||||
new FileSystemResource(new File(findWorkDir(), "client-cert.jks")), "changeit", original.getTrustStore(),
|
||||
original.getTrustStorePassword());
|
||||
SslConfiguration sslConfiguration = new SslConfiguration(new FileSystemResource(
|
||||
new File(findWorkDir(), "client-cert.jks")), "changeit",
|
||||
original.getTrustStore(), original.getTrustStorePassword());
|
||||
|
||||
return sslConfiguration;
|
||||
}
|
||||
|
||||
@@ -15,12 +15,9 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
@@ -30,6 +27,12 @@ import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ClientCertificateAuthentication}.
|
||||
*
|
||||
@@ -51,12 +54,19 @@ public class ClientCertificateAuthenticationUnitTests {
|
||||
@Test
|
||||
public void loginShouldObtainToken() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/cert/login")) //
|
||||
.andExpect(method(HttpMethod.POST)) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{" + "\"auth\":{\"client_token\":\"my-token\", \"renewable\": true, \"lease_duration\": 10}" + "}"));
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/auth/cert/login"))
|
||||
//
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
//
|
||||
.andRespond(
|
||||
withSuccess()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{"
|
||||
+ "\"auth\":{\"client_token\":\"my-token\", \"renewable\": true, \"lease_duration\": 10}"
|
||||
+ "}"));
|
||||
|
||||
ClientCertificateAuthentication sut = new ClientCertificateAuthentication(vaultClient);
|
||||
ClientCertificateAuthentication sut = new ClientCertificateAuthentication(
|
||||
vaultClient);
|
||||
|
||||
VaultToken login = sut.login();
|
||||
|
||||
|
||||
@@ -15,12 +15,10 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -36,6 +34,10 @@ import org.springframework.vault.util.IntegrationTestSupport;
|
||||
import org.springframework.vault.util.Settings;
|
||||
import org.springframework.vault.util.TestRestTemplateFactory;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link CubbyholeAuthentication}.
|
||||
*
|
||||
@@ -49,13 +51,15 @@ public class CubbyholeAuthenticationIntegrationTests extends IntegrationTestSupp
|
||||
VaultResponseEntity<VaultResponse> response = prepare().getVaultOperations()
|
||||
.doWithVault(new SessionCallback<VaultResponseEntity<VaultResponse>>() {
|
||||
@Override
|
||||
public VaultResponseEntity<VaultResponse> doWithVault(VaultSession session) {
|
||||
public VaultResponseEntity<VaultResponse> doWithVault(
|
||||
VaultSession session) {
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("X-Vault-Wrap-TTL", "10m");
|
||||
|
||||
return session.exchange("auth/token/create", HttpMethod.POST, new HttpEntity<Object>(headers),
|
||||
VaultResponse.class, null);
|
||||
return session.exchange("auth/token/create", HttpMethod.POST,
|
||||
new HttpEntity<Object>(headers), VaultResponse.class,
|
||||
null);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -69,10 +73,11 @@ public class CubbyholeAuthenticationIntegrationTests extends IntegrationTestSupp
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions.builder()
|
||||
.initialToken(VaultToken.of(initialToken)).wrapped().build();
|
||||
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings.createSslConfiguration()),
|
||||
new VaultEndpoint());
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings
|
||||
.createSslConfiguration()), new VaultEndpoint());
|
||||
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options,
|
||||
vaultClient);
|
||||
VaultToken login = authentication.login();
|
||||
assertThat(login.getToken()).doesNotContain(Settings.token().getToken());
|
||||
}
|
||||
@@ -83,14 +88,16 @@ public class CubbyholeAuthenticationIntegrationTests extends IntegrationTestSupp
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions.builder()
|
||||
.initialToken(VaultToken.of("Hello")).wrapped().build();
|
||||
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings.createSslConfiguration()),
|
||||
new VaultEndpoint());
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(Settings
|
||||
.createSslConfiguration()), new VaultEndpoint());
|
||||
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options,
|
||||
vaultClient);
|
||||
try {
|
||||
authentication.login();
|
||||
fail("Missing VaultException");
|
||||
} catch (VaultException e) {
|
||||
}
|
||||
catch (VaultException e) {
|
||||
assertThat(e).hasMessageContaining("Cannot retrieve Token from cubbyhole")
|
||||
.hasMessageContaining("permission denied");
|
||||
}
|
||||
|
||||
@@ -15,12 +15,9 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
@@ -30,6 +27,13 @@ import org.springframework.vault.client.VaultException;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CubbyholeAuthentication}.
|
||||
*
|
||||
@@ -51,18 +55,24 @@ public class CubbyholeAuthenticationUnitTests {
|
||||
@Test
|
||||
public void shouldLoginUsingWrappedLogin() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/cubbyhole/response")) //
|
||||
.andExpect(method(HttpMethod.GET)) //
|
||||
.andExpect(header(VaultClient.VAULT_TOKEN, "hello")) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{\"data\":{\"response\":\"{\\\"request_id\\\":\\\"058222ef-9ab9-ff39-f087-9d5bee64e46d\\\","
|
||||
+ "\\\"auth\\\":{\\\"client_token\\\":\\\"5e6332cf-f003-6369-8cba-5bce2330f6cc\\\","
|
||||
+ "\\\"accessor\\\":\\\"46b6aebb-187f-932a-26d7-4f3d86a68319\\\"}}\" } }"));
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/cubbyhole/response"))
|
||||
//
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
//
|
||||
.andExpect(header(VaultClient.VAULT_TOKEN, "hello"))
|
||||
//
|
||||
.andRespond(
|
||||
withSuccess()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{\"data\":{\"response\":\"{\\\"request_id\\\":\\\"058222ef-9ab9-ff39-f087-9d5bee64e46d\\\","
|
||||
+ "\\\"auth\\\":{\\\"client_token\\\":\\\"5e6332cf-f003-6369-8cba-5bce2330f6cc\\\","
|
||||
+ "\\\"accessor\\\":\\\"46b6aebb-187f-932a-26d7-4f3d86a68319\\\"}}\" } }"));
|
||||
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions.builder()
|
||||
.initialToken(VaultToken.of("hello")).wrapped().build();
|
||||
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options,
|
||||
vaultClient);
|
||||
|
||||
VaultToken login = authentication.login();
|
||||
|
||||
@@ -75,14 +85,18 @@ public class CubbyholeAuthenticationUnitTests {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/cubbyhole/token")) //
|
||||
.andExpect(method(HttpMethod.GET)) //
|
||||
.andExpect(header(VaultClient.VAULT_TOKEN, "hello")) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{\"data\":{\"mytoken\":\"058222ef-9ab9-ff39-f087-9d5bee64e46d\"} }"));
|
||||
.andExpect(header(VaultClient.VAULT_TOKEN, "hello"))
|
||||
//
|
||||
.andRespond(
|
||||
withSuccess()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body("{\"data\":{\"mytoken\":\"058222ef-9ab9-ff39-f087-9d5bee64e46d\"} }"));
|
||||
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions.builder()
|
||||
.initialToken(VaultToken.of("hello")).path("cubbyhole/token").build();
|
||||
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options,
|
||||
vaultClient);
|
||||
|
||||
VaultToken login = authentication.login();
|
||||
|
||||
@@ -93,20 +107,27 @@ public class CubbyholeAuthenticationUnitTests {
|
||||
@Test
|
||||
public void shouldFailUsingStoredLoginNoData() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/cubbyhole/token")) //
|
||||
.andExpect(method(HttpMethod.GET)) //
|
||||
.andExpect(header(VaultClient.VAULT_TOKEN, "hello")) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON).body("{\"data\":{} }"));
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/cubbyhole/token"))
|
||||
//
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
//
|
||||
.andExpect(header(VaultClient.VAULT_TOKEN, "hello"))
|
||||
//
|
||||
.andRespond(
|
||||
withSuccess().contentType(MediaType.APPLICATION_JSON).body(
|
||||
"{\"data\":{} }"));
|
||||
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions.builder()
|
||||
.initialToken(VaultToken.of("hello")).path("cubbyhole/token").build();
|
||||
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options,
|
||||
vaultClient);
|
||||
|
||||
try {
|
||||
authentication.login();
|
||||
fail("Missing VaultException");
|
||||
} catch (VaultException e) {
|
||||
}
|
||||
catch (VaultException e) {
|
||||
assertThat(e).hasMessageContaining("does not contain a token");
|
||||
}
|
||||
}
|
||||
@@ -114,20 +135,27 @@ public class CubbyholeAuthenticationUnitTests {
|
||||
@Test
|
||||
public void shouldFailUsingStoredMultipleEntries() throws Exception {
|
||||
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/cubbyhole/token")) //
|
||||
.andExpect(method(HttpMethod.GET)) //
|
||||
.andExpect(header(VaultClient.VAULT_TOKEN, "hello")) //
|
||||
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON).body("{\"data\":{\"key1\":1, \"key2\":2} }"));
|
||||
mockRest.expect(requestTo("https://localhost:8200/v1/cubbyhole/token"))
|
||||
//
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
//
|
||||
.andExpect(header(VaultClient.VAULT_TOKEN, "hello"))
|
||||
//
|
||||
.andRespond(
|
||||
withSuccess().contentType(MediaType.APPLICATION_JSON).body(
|
||||
"{\"data\":{\"key1\":1, \"key2\":2} }"));
|
||||
|
||||
CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions.builder()
|
||||
.initialToken(VaultToken.of("hello")).path("cubbyhole/token").build();
|
||||
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, vaultClient);
|
||||
CubbyholeAuthentication authentication = new CubbyholeAuthentication(options,
|
||||
vaultClient);
|
||||
|
||||
try {
|
||||
authentication.login();
|
||||
fail("Missing VaultException");
|
||||
} catch (VaultException e) {
|
||||
}
|
||||
catch (VaultException e) {
|
||||
assertThat(e).hasMessageContaining("does not contain an unique token");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link IpAddressUserId}.
|
||||
*
|
||||
@@ -33,6 +33,7 @@ public class IpAddressUserIdTests {
|
||||
|
||||
String userId = new IpAddressUserId().createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(
|
||||
Pattern.compile("[a-f]"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -31,6 +30,8 @@ import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.support.VaultTokenRequest;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link LifecycleAwareSessionManager}.
|
||||
*
|
||||
@@ -46,8 +47,8 @@ public class LifecycleAwareSessionManagerIntegrationTests extends IntegrationTes
|
||||
LoginToken loginToken = createLoginToken();
|
||||
TokenAuthentication tokenAuthentication = new TokenAuthentication(loginToken);
|
||||
|
||||
LifecycleAwareSessionManager sessionManager = new LifecycleAwareSessionManager(tokenAuthentication, taskExecutor,
|
||||
prepare().getVaultClient());
|
||||
LifecycleAwareSessionManager sessionManager = new LifecycleAwareSessionManager(
|
||||
tokenAuthentication, taskExecutor, prepare().getVaultClient());
|
||||
|
||||
assertThat(sessionManager.getSessionToken()).isSameAs(loginToken);
|
||||
}
|
||||
@@ -56,7 +57,8 @@ public class LifecycleAwareSessionManagerIntegrationTests extends IntegrationTes
|
||||
@Test
|
||||
public void shouldRenewToken() {
|
||||
|
||||
VaultTokenOperations tokenOperations = prepare().getVaultOperations().opsForToken();
|
||||
VaultTokenOperations tokenOperations = prepare().getVaultOperations()
|
||||
.opsForToken();
|
||||
|
||||
VaultTokenRequest tokenRequest = new VaultTokenRequest();
|
||||
tokenRequest.setRenewable(true);
|
||||
@@ -65,11 +67,12 @@ public class LifecycleAwareSessionManagerIntegrationTests extends IntegrationTes
|
||||
|
||||
VaultToken token = tokenOperations.create(tokenRequest).getToken();
|
||||
|
||||
TokenAuthentication tokenAuthentication = new TokenAuthentication(LoginToken.renewable(token.getToken(), 0));
|
||||
TokenAuthentication tokenAuthentication = new TokenAuthentication(
|
||||
LoginToken.renewable(token.getToken(), 0));
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
LifecycleAwareSessionManager sessionManager = new LifecycleAwareSessionManager(tokenAuthentication, taskExecutor,
|
||||
prepare().getVaultClient()) {
|
||||
LifecycleAwareSessionManager sessionManager = new LifecycleAwareSessionManager(
|
||||
tokenAuthentication, taskExecutor, prepare().getVaultClient()) {
|
||||
@Override
|
||||
public VaultToken getSessionToken() {
|
||||
|
||||
@@ -90,30 +93,34 @@ public class LifecycleAwareSessionManagerIntegrationTests extends IntegrationTes
|
||||
final LoginToken loginToken = createLoginToken();
|
||||
TokenAuthentication tokenAuthentication = new TokenAuthentication(loginToken);
|
||||
|
||||
LifecycleAwareSessionManager sessionManager = new LifecycleAwareSessionManager(tokenAuthentication, taskExecutor,
|
||||
prepare().getVaultClient());
|
||||
LifecycleAwareSessionManager sessionManager = new LifecycleAwareSessionManager(
|
||||
tokenAuthentication, taskExecutor, prepare().getVaultClient());
|
||||
|
||||
sessionManager.getSessionToken();
|
||||
sessionManager.destroy();
|
||||
|
||||
prepare().getVaultOperations().doWithVault(new VaultOperations.SessionCallback<Object>() {
|
||||
prepare().getVaultOperations().doWithVault(
|
||||
new VaultOperations.SessionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object doWithVault(VaultOperations.VaultSession session) {
|
||||
@Override
|
||||
public Object doWithVault(VaultOperations.VaultSession session) {
|
||||
|
||||
VaultResponseEntity<Map> entity = session
|
||||
.getForEntity(String.format("auth/token/lookup/%s", loginToken.getToken()), Map.class);
|
||||
VaultResponseEntity<Map> entity = session.getForEntity(
|
||||
String.format("auth/token/lookup/%s",
|
||||
loginToken.getToken()), Map.class);
|
||||
|
||||
// Compatibility across Vault versions.
|
||||
assertThat(entity.getStatusCode()).isIn(HttpStatus.BAD_REQUEST, HttpStatus.NOT_FOUND, HttpStatus.FORBIDDEN);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
// Compatibility across Vault versions.
|
||||
assertThat(entity.getStatusCode()).isIn(HttpStatus.BAD_REQUEST,
|
||||
HttpStatus.NOT_FOUND, HttpStatus.FORBIDDEN);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private LoginToken createLoginToken() {
|
||||
|
||||
VaultTokenOperations tokenOperations = prepare().getVaultOperations().opsForToken();
|
||||
VaultTokenOperations tokenOperations = prepare().getVaultOperations()
|
||||
.opsForToken();
|
||||
VaultToken token = tokenOperations.createOrphan().getToken();
|
||||
|
||||
return LoginToken.of(token.getToken());
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -27,6 +24,7 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.scheduling.Trigger;
|
||||
@@ -35,6 +33,15 @@ import org.springframework.vault.client.VaultClient;
|
||||
import org.springframework.vault.client.VaultResponseEntity;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LifecycleAwareSessionManager}.
|
||||
*
|
||||
@@ -43,19 +50,24 @@ import org.springframework.vault.support.VaultToken;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LifecycleAwareSessionManagerUnitTests {
|
||||
|
||||
@Mock private ClientAuthentication clientAuthentication;
|
||||
@Mock
|
||||
private ClientAuthentication clientAuthentication;
|
||||
|
||||
@Mock private AsyncTaskExecutor taskExecutor;
|
||||
@Mock
|
||||
private AsyncTaskExecutor taskExecutor;
|
||||
|
||||
@Mock private ThreadPoolTaskScheduler taskScheduler;
|
||||
@Mock
|
||||
private ThreadPoolTaskScheduler taskScheduler;
|
||||
|
||||
@Mock private VaultClient vaultClient;
|
||||
@Mock
|
||||
private VaultClient vaultClient;
|
||||
|
||||
private LifecycleAwareSessionManager sessionManager;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
sessionManager = new LifecycleAwareSessionManager(clientAuthentication, taskExecutor, vaultClient);
|
||||
sessionManager = new LifecycleAwareSessionManager(clientAuthentication,
|
||||
taskExecutor, vaultClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,14 +83,17 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
|
||||
when(clientAuthentication.login()).thenReturn(LoginToken.of("login"));
|
||||
|
||||
when(vaultClient.postForEntity(eq("auth/token/revoke-self"), eq(LoginToken.of("login")), ArgumentMatchers.any(),
|
||||
any(Class.class))).thenReturn(new ResponseEntity<Object>(null, HttpStatus.OK, null, null));
|
||||
when(
|
||||
vaultClient.postForEntity(eq("auth/token/revoke-self"),
|
||||
eq(LoginToken.of("login")), ArgumentMatchers.any(),
|
||||
any(Class.class))).thenReturn(
|
||||
new ResponseEntity<Object>(null, HttpStatus.OK, null, null));
|
||||
|
||||
sessionManager.renewToken();
|
||||
sessionManager.destroy();
|
||||
|
||||
verify(vaultClient).postForEntity(eq("auth/token/revoke-self"), eq(LoginToken.of("login")), ArgumentMatchers.any(),
|
||||
any(Class.class));
|
||||
verify(vaultClient).postForEntity(eq("auth/token/revoke-self"),
|
||||
eq(LoginToken.of("login")), ArgumentMatchers.any(), any(Class.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,14 +112,18 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
|
||||
when(clientAuthentication.login()).thenReturn(LoginToken.of("login"));
|
||||
|
||||
when(vaultClient.postForEntity(eq("auth/token/revoke-self"), eq(LoginToken.of("login")), ArgumentMatchers.any(),
|
||||
any(Class.class))).thenReturn(new ResponseEntity<Object>(null, HttpStatus.INTERNAL_SERVER_ERROR, null, null));
|
||||
when(
|
||||
vaultClient.postForEntity(eq("auth/token/revoke-self"),
|
||||
eq(LoginToken.of("login")), ArgumentMatchers.any(),
|
||||
any(Class.class))).thenReturn(
|
||||
new ResponseEntity<Object>(null, HttpStatus.INTERNAL_SERVER_ERROR, null,
|
||||
null));
|
||||
|
||||
sessionManager.renewToken();
|
||||
sessionManager.destroy();
|
||||
|
||||
verify(vaultClient).postForEntity(eq("auth/token/revoke-self"), eq(LoginToken.of("login")), ArgumentMatchers.any(),
|
||||
any(Class.class));
|
||||
verify(vaultClient).postForEntity(eq("auth/token/revoke-self"),
|
||||
eq(LoginToken.of("login")), ArgumentMatchers.any(), any(Class.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,9 +140,11 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
public void shouldRunTokenRenewal() {
|
||||
|
||||
when(clientAuthentication.login()).thenReturn(LoginToken.renewable("login", 5));
|
||||
when(vaultClient.postForEntity(eq("auth/token/renew-self"), eq(LoginToken.renewable("login", 5)),
|
||||
ArgumentMatchers.any(), any(Class.class)))
|
||||
.thenReturn(new ResponseEntity<Object>(null, HttpStatus.OK, null, null));
|
||||
when(
|
||||
vaultClient.postForEntity(eq("auth/token/renew-self"),
|
||||
eq(LoginToken.renewable("login", 5)), ArgumentMatchers.any(),
|
||||
any(Class.class))).thenReturn(
|
||||
new ResponseEntity<Object>(null, HttpStatus.OK, null, null));
|
||||
|
||||
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
|
||||
|
||||
@@ -131,8 +152,9 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
verify(taskExecutor).execute(runnableCaptor.capture());
|
||||
|
||||
runnableCaptor.getValue().run();
|
||||
verify(vaultClient).postForEntity(eq("auth/token/renew-self"), eq(LoginToken.renewable("login", 5)),
|
||||
ArgumentMatchers.any(), any(Class.class));
|
||||
verify(vaultClient).postForEntity(eq("auth/token/renew-self"),
|
||||
eq(LoginToken.renewable("login", 5)), ArgumentMatchers.any(),
|
||||
any(Class.class));
|
||||
verify(clientAuthentication, times(1)).login();
|
||||
}
|
||||
|
||||
@@ -140,9 +162,11 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
public void shouldReScheduleTokenRenewalAfterSucessfulRenewal() {
|
||||
|
||||
when(clientAuthentication.login()).thenReturn(LoginToken.renewable("login", 5));
|
||||
when(vaultClient.postForEntity(eq("auth/token/renew-self"), eq(LoginToken.renewable("login", 5)),
|
||||
ArgumentMatchers.any(), any(Class.class)))
|
||||
.thenReturn(new ResponseEntity<Object>(null, HttpStatus.OK, null, null));
|
||||
when(
|
||||
vaultClient.postForEntity(eq("auth/token/renew-self"),
|
||||
eq(LoginToken.renewable("login", 5)), ArgumentMatchers.any(),
|
||||
any(Class.class))).thenReturn(
|
||||
new ResponseEntity<Object>(null, HttpStatus.OK, null, null));
|
||||
|
||||
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
|
||||
|
||||
@@ -157,7 +181,8 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
@Test
|
||||
public void shouldUseTaskScheduler() {
|
||||
|
||||
sessionManager = new LifecycleAwareSessionManager(clientAuthentication, taskScheduler, vaultClient);
|
||||
sessionManager = new LifecycleAwareSessionManager(clientAuthentication,
|
||||
taskScheduler, vaultClient);
|
||||
|
||||
when(clientAuthentication.login()).thenReturn(LoginToken.renewable("login", 5));
|
||||
|
||||
@@ -174,9 +199,12 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
public void shouldNotReScheduleTokenRenewalAfterFailedRenewal() {
|
||||
|
||||
when(clientAuthentication.login()).thenReturn(LoginToken.renewable("login", 5));
|
||||
when(vaultClient.postForEntity(eq("auth/token/renew-self"), eq(LoginToken.renewable("login", 5)),
|
||||
ArgumentMatchers.any(), any(Class.class)))
|
||||
.thenReturn(new ResponseEntity<Object>(null, HttpStatus.INTERNAL_SERVER_ERROR, null, null));
|
||||
when(
|
||||
vaultClient.postForEntity(eq("auth/token/renew-self"),
|
||||
eq(LoginToken.renewable("login", 5)), ArgumentMatchers.any(),
|
||||
any(Class.class))).thenReturn(
|
||||
new ResponseEntity<Object>(null, HttpStatus.INTERNAL_SERVER_ERROR, null,
|
||||
null));
|
||||
|
||||
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
|
||||
|
||||
@@ -195,7 +223,8 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
|
||||
sessionManager.renewToken();
|
||||
|
||||
assertThat(sessionManager.getSessionToken()).isEqualTo(LoginToken.renewable("login", 5));
|
||||
assertThat(sessionManager.getSessionToken()).isEqualTo(
|
||||
LoginToken.renewable("login", 5));
|
||||
verify(clientAuthentication, times(1)).login();
|
||||
}
|
||||
|
||||
@@ -203,8 +232,10 @@ public class LifecycleAwareSessionManagerUnitTests {
|
||||
public void renewShouldReportFalseIfTokenRenewalFails() {
|
||||
|
||||
when(clientAuthentication.login()).thenReturn(LoginToken.renewable("login", 5));
|
||||
when(vaultClient.postForEntity(anyString(), any(VaultToken.class), ArgumentMatchers.any(), any(Class.class)))
|
||||
.thenReturn(new ResponseEntity<Object>(null, HttpStatus.BAD_REQUEST, null, null));
|
||||
when(
|
||||
vaultClient.postForEntity(anyString(), any(VaultToken.class),
|
||||
ArgumentMatchers.any(), any(Class.class))).thenReturn(
|
||||
new ResponseEntity<Object>(null, HttpStatus.BAD_REQUEST, null, null));
|
||||
|
||||
sessionManager.getSessionToken();
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LoginToken}.
|
||||
*
|
||||
@@ -37,8 +37,11 @@ public class LoginTokenUnitTests {
|
||||
@Test
|
||||
public void toStringShouldPrintFields() {
|
||||
|
||||
assertThat(LoginToken.of("token").toString()).isEqualTo("LoginToken(renewable=false, leaseDuration=0)");
|
||||
assertThat(LoginToken.of("token", 1).toString()).isEqualTo("LoginToken(renewable=false, leaseDuration=1)");
|
||||
assertThat(LoginToken.renewable("token", 1).toString()).isEqualTo("LoginToken(renewable=true, leaseDuration=1)");
|
||||
assertThat(LoginToken.of("token").toString()).isEqualTo(
|
||||
"LoginToken(renewable=false, leaseDuration=0)");
|
||||
assertThat(LoginToken.of("token", 1).toString()).isEqualTo(
|
||||
"LoginToken(renewable=false, leaseDuration=1)");
|
||||
assertThat(LoginToken.renewable("token", 1).toString()).isEqualTo(
|
||||
"LoginToken(renewable=true, leaseDuration=1)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,17 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MacAddressUserId}.
|
||||
*
|
||||
@@ -37,7 +38,8 @@ public class MacAddressUserIdUnitTests {
|
||||
|
||||
String userId = new MacAddressUserId().createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(
|
||||
Pattern.compile("[a-f]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -48,7 +50,8 @@ public class MacAddressUserIdUnitTests {
|
||||
|
||||
String userId = new MacAddressUserId(index).createUserId();
|
||||
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(Pattern.compile("[a-f]"));
|
||||
assertThat(userId).matches(Pattern.compile("[0-9A-F]+")).doesNotMatch(
|
||||
Pattern.compile("[a-f]"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,8 +62,8 @@ public class MacAddressUserIdUnitTests {
|
||||
*/
|
||||
private int getValidNetworkInterfaceIndex() throws SocketException {
|
||||
|
||||
NetworkInterface[] networkInterfaces = CollectionUtils.toArray(NetworkInterface.getNetworkInterfaces(),
|
||||
new NetworkInterface[0]);
|
||||
NetworkInterface[] networkInterfaces = CollectionUtils.toArray(
|
||||
NetworkInterface.getNetworkInterfaces(), new NetworkInterface[0]);
|
||||
|
||||
int index = -1;
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
*/
|
||||
package org.springframework.vault.client;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link VaultEndpoint}.
|
||||
*
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
*/
|
||||
package org.springframework.vault.config;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -35,6 +34,8 @@ import org.springframework.vault.util.Settings;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ClientHttpRequestFactory}.
|
||||
*
|
||||
@@ -47,8 +48,8 @@ public class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
@Test
|
||||
public void httpComponentsClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = HttpComponents.usingHttpComponents(new ClientOptions(),
|
||||
Settings.createSslConfiguration());
|
||||
ClientHttpRequestFactory factory = HttpComponents.usingHttpComponents(
|
||||
new ClientOptions(), Settings.createSslConfiguration());
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
@@ -62,7 +63,8 @@ public class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
@Test
|
||||
public void nettyClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = Netty.usingNetty(new ClientOptions(), Settings.createSslConfiguration());
|
||||
ClientHttpRequestFactory factory = Netty.usingNetty(new ClientOptions(),
|
||||
Settings.createSslConfiguration());
|
||||
((InitializingBean) factory).afterPropertiesSet();
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
@@ -77,7 +79,8 @@ public class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
@Test
|
||||
public void okHttpClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = OkHttp.usingOkHttp(new ClientOptions(), Settings.createSslConfiguration());
|
||||
ClientHttpRequestFactory factory = OkHttp.usingOkHttp(new ClientOptions(),
|
||||
Settings.createSslConfiguration());
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
@@ -92,9 +95,11 @@ public class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
|
||||
// Uninitialized and sealed can cause status 500
|
||||
try {
|
||||
ResponseEntity<String> responseEntity = template.exchange(url, HttpMethod.GET, null, String.class);
|
||||
ResponseEntity<String> responseEntity = template.exchange(url,
|
||||
HttpMethod.GET, null, String.class);
|
||||
return responseEntity.getBody();
|
||||
} catch (HttpStatusCodeException e) {
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
return e.getResponseBodyAsString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.springframework.vault.util.Settings.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
@@ -26,8 +24,11 @@ import java.util.Map;
|
||||
import org.assertj.core.util.Files;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.springframework.vault.util.Settings.findWorkDir;
|
||||
|
||||
/**
|
||||
* Integration test to request certificates from the Vault PKI backend.
|
||||
*
|
||||
@@ -47,12 +48,15 @@ public class PkiSecretIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
File workDir = findWorkDir(new File(System.getProperty("user.dir")));
|
||||
|
||||
String cert = Files.contentOf(new File(workDir, "ca/certs/intermediate.cert.pem"), StandardCharsets.US_ASCII);
|
||||
|
||||
String key = Files.contentOf(new File(workDir, "ca/private/intermediate.decrypted.key.pem"),
|
||||
String cert = Files.contentOf(
|
||||
new File(workDir, "ca/certs/intermediate.cert.pem"),
|
||||
StandardCharsets.US_ASCII);
|
||||
|
||||
Map<String, String> pembundle = Collections.singletonMap("pem_bundle", cert + key);
|
||||
String key = Files.contentOf(new File(workDir,
|
||||
"ca/private/intermediate.decrypted.key.pem"), StandardCharsets.US_ASCII);
|
||||
|
||||
Map<String, String> pembundle = Collections
|
||||
.singletonMap("pem_bundle", cert + key);
|
||||
|
||||
VaultOperations vaultOperations = prepare().getVaultOperations();
|
||||
vaultOperations.write("pki/config/ca", pembundle);
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.vault.util.Settings.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -27,6 +24,7 @@ import org.assertj.core.util.Files;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
@@ -36,6 +34,9 @@ import org.springframework.vault.support.VaultCertificateRequest;
|
||||
import org.springframework.vault.support.VaultCertificateResponse;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.vault.util.Settings.findWorkDir;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultPkiTemplate} through {@link VaultPkiOperations}.
|
||||
*
|
||||
@@ -45,7 +46,8 @@ import org.springframework.vault.util.IntegrationTestSupport;
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
@Autowired
|
||||
private VaultOperations vaultOperations;
|
||||
|
||||
private VaultPkiOperations pkiOperations;
|
||||
|
||||
@@ -59,10 +61,13 @@ public class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
}
|
||||
|
||||
File workDir = findWorkDir(new File(System.getProperty("user.dir")));
|
||||
String cert = Files.contentOf(new File(workDir, "ca/certs/intermediate.cert.pem"), "US-ASCII");
|
||||
String key = Files.contentOf(new File(workDir, "ca/private/intermediate.decrypted.key.pem"), "US-ASCII");
|
||||
String cert = Files.contentOf(
|
||||
new File(workDir, "ca/certs/intermediate.cert.pem"), "US-ASCII");
|
||||
String key = Files.contentOf(new File(workDir,
|
||||
"ca/private/intermediate.decrypted.key.pem"), "US-ASCII");
|
||||
|
||||
Map<String, String> pembundle = Collections.singletonMap("pem_bundle", cert + key);
|
||||
Map<String, String> pembundle = Collections
|
||||
.singletonMap("pem_bundle", cert + key);
|
||||
|
||||
vaultOperations.write("pki/config/ca", pembundle);
|
||||
|
||||
@@ -79,9 +84,11 @@ public class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
@Test
|
||||
public void issueCertificateShouldCreateCertificate() {
|
||||
|
||||
VaultCertificateRequest request = VaultCertificateRequest.create("hello.example.com");
|
||||
VaultCertificateRequest request = VaultCertificateRequest
|
||||
.create("hello.example.com");
|
||||
|
||||
VaultCertificateResponse certificateResponse = pkiOperations.issueCertificate("testrole", request);
|
||||
VaultCertificateResponse certificateResponse = pkiOperations.issueCertificate(
|
||||
"testrole", request);
|
||||
|
||||
CertificateBundle data = certificateResponse.getData();
|
||||
|
||||
@@ -89,7 +96,8 @@ public class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
assertThat(data.getCertificate()).isNotEmpty();
|
||||
assertThat(data.getIssuingCaCertificate()).isNotEmpty();
|
||||
assertThat(data.getSerialNumber()).isNotEmpty();
|
||||
assertThat(data.getX509Certificate().getSubjectX500Principal().getName()).isEqualTo("CN=hello.example.com");
|
||||
assertThat(data.getX509Certificate().getSubjectX500Principal().getName())
|
||||
.isEqualTo("CN=hello.example.com");
|
||||
}
|
||||
|
||||
@Test(expected = VaultException.class)
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
@@ -30,6 +29,8 @@ import org.springframework.vault.support.VaultMount;
|
||||
import org.springframework.vault.support.VaultUnsealStatus;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultSysTemplate} through {@link VaultSysOperations}.
|
||||
*
|
||||
@@ -39,7 +40,8 @@ import org.springframework.vault.util.IntegrationTestSupport;
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultSysTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
@Autowired
|
||||
private VaultOperations vaultOperations;
|
||||
|
||||
private VaultSysOperations adminOperations;
|
||||
|
||||
@@ -102,7 +104,8 @@ public class VaultSysTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
adminOperations.authUnmount("other");
|
||||
}
|
||||
|
||||
VaultMount mount = VaultMount.builder().type("userpass").description("hello, world").build();
|
||||
VaultMount mount = VaultMount.builder().type("userpass")
|
||||
.description("hello, world").build();
|
||||
|
||||
adminOperations.authMount("other", mount);
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ import org.springframework.vault.util.IntegrationTestSupport;
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultTemplateGenericIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
@Autowired
|
||||
private VaultOperations vaultOperations;
|
||||
|
||||
@Test
|
||||
public void readShouldReturnAbsentKey() throws Exception {
|
||||
@@ -69,7 +70,8 @@ public class VaultTemplateGenericIntegrationTests extends IntegrationTestSupport
|
||||
|
||||
vaultOperations.write("secret/mykey", data);
|
||||
|
||||
VaultResponseSupport<Person> read = vaultOperations.read("secret/mykey", Person.class);
|
||||
VaultResponseSupport<Person> read = vaultOperations.read("secret/mykey",
|
||||
Person.class);
|
||||
assertThat(read).isNotNull();
|
||||
|
||||
Person person = read.getData();
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
@@ -30,6 +29,8 @@ import org.springframework.vault.support.VaultMount;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultTemplate} using the {@code transit} backend.
|
||||
*
|
||||
@@ -39,7 +40,8 @@ import org.springframework.vault.util.IntegrationTestSupport;
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
@Autowired
|
||||
private VaultOperations vaultOperations;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
@@ -50,15 +52,18 @@ public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport
|
||||
adminOperations.mount("transit", VaultMount.create("transit"));
|
||||
|
||||
vaultOperations.write("transit/keys/mykey", null);
|
||||
vaultOperations.write("transit/keys/derived", Collections.singletonMap("derived", true));
|
||||
vaultOperations.write("transit/keys/derived",
|
||||
Collections.singletonMap("derived", true));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncrypt() throws Exception {
|
||||
|
||||
VaultResponse response = vaultOperations.write("transit/encrypt/mykey",
|
||||
Collections.singletonMap("plaintext", Base64.encodeBase64String("that message is secret".getBytes())));
|
||||
VaultResponse response = vaultOperations.write(
|
||||
"transit/encrypt/mykey",
|
||||
Collections.singletonMap("plaintext",
|
||||
Base64.encodeBase64String("that message is secret".getBytes())));
|
||||
|
||||
assertThat((String) response.getData().get("ciphertext")).isNotEmpty();
|
||||
}
|
||||
@@ -66,12 +71,17 @@ public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport
|
||||
@Test
|
||||
public void shouldEncryptAndDecrypt() throws Exception {
|
||||
|
||||
VaultResponse response = vaultOperations.write("transit/encrypt/mykey",
|
||||
Collections.singletonMap("plaintext", Base64.encodeBase64String("that message is secret".getBytes())));
|
||||
VaultResponse response = vaultOperations.write(
|
||||
"transit/encrypt/mykey",
|
||||
Collections.singletonMap("plaintext",
|
||||
Base64.encodeBase64String("that message is secret".getBytes())));
|
||||
|
||||
VaultResponse decrypted = vaultOperations.write("transit/decrypt/mykey",
|
||||
Collections.singletonMap("ciphertext", response.getData().get("ciphertext")));
|
||||
VaultResponse decrypted = vaultOperations.write(
|
||||
"transit/decrypt/mykey",
|
||||
Collections.singletonMap("ciphertext",
|
||||
response.getData().get("ciphertext")));
|
||||
|
||||
assertThat((String) decrypted.getData().get("plaintext")).isEqualTo(Base64.encodeBase64String("that message is secret".getBytes()));
|
||||
assertThat((String) decrypted.getData().get("plaintext")).isEqualTo(
|
||||
Base64.encodeBase64String("that message is secret".getBytes()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,12 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -33,6 +32,8 @@ import org.springframework.vault.support.VaultTokenRequest;
|
||||
import org.springframework.vault.support.VaultTokenResponse;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultTokenTemplate} through {@link VaultTokenOperations}.
|
||||
*
|
||||
@@ -42,7 +43,8 @@ import org.springframework.vault.util.IntegrationTestSupport;
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultTokenTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
@Autowired
|
||||
private VaultOperations vaultOperations;
|
||||
private VaultTokenOperations tokenOperations;
|
||||
|
||||
@Before
|
||||
@@ -70,7 +72,8 @@ public class VaultTokenTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
tokenRequest.setId("HELLO-WORLD");
|
||||
|
||||
VaultTokenResponse tokenResponse = tokenOperations.create(tokenRequest);
|
||||
assertThat(tokenResponse.getAuth()).containsEntry("client_token", tokenRequest.getId());
|
||||
assertThat(tokenResponse.getAuth()).containsEntry("client_token",
|
||||
tokenRequest.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,7 +96,8 @@ public class VaultTokenTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
tokenRequest.setId("HELLO-WORLD");
|
||||
|
||||
VaultTokenResponse tokenResponse = tokenOperations.createOrphan(tokenRequest);
|
||||
assertThat(tokenResponse.getAuth()).containsEntry("client_token", tokenRequest.getId());
|
||||
assertThat(tokenResponse.getAuth()).containsEntry("client_token",
|
||||
tokenRequest.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,8 +131,9 @@ public class VaultTokenTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
VaultResponseEntity<String> response = lookupSelf(tokenResponse);
|
||||
|
||||
assertThat(response.getStatusCode()).isIn(/* <= Vault 0.6.0 */ HttpStatus.BAD_REQUEST,
|
||||
/* >= Vault 0.6.1 */ HttpStatus.FORBIDDEN);
|
||||
assertThat(response.getStatusCode()).isIn(
|
||||
/* <= Vault 0.6.0 */HttpStatus.BAD_REQUEST,
|
||||
/* >= Vault 0.6.1 */HttpStatus.FORBIDDEN);
|
||||
assertThat(response.getMessage()).isEqualTo("permission denied");
|
||||
}
|
||||
|
||||
@@ -144,11 +149,13 @@ public class VaultTokenTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
private VaultResponseEntity<String> lookupSelf(final VaultTokenResponse tokenResponse) {
|
||||
|
||||
return vaultOperations.doWithVault(new VaultOperations.ClientCallback<VaultResponseEntity<String>>() {
|
||||
@Override
|
||||
public VaultResponseEntity<String> doWithVault(VaultClient client) {
|
||||
return client.getForEntity("auth/token/lookup-self", tokenResponse.getToken(), String.class);
|
||||
}
|
||||
});
|
||||
return vaultOperations
|
||||
.doWithVault(new VaultOperations.ClientCallback<VaultResponseEntity<String>>() {
|
||||
@Override
|
||||
public VaultResponseEntity<String> doWithVault(VaultClient client) {
|
||||
return client.getForEntity("auth/token/lookup-self",
|
||||
tokenResponse.getToken(), String.class);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,10 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
@@ -32,8 +30,12 @@ import org.springframework.vault.support.VaultTransitKeyConfiguration;
|
||||
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultTransitTemplate} through {@link VaultTransitOperations}.
|
||||
* Integration tests for {@link VaultTransitTemplate} through
|
||||
* {@link VaultTransitOperations}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -41,7 +43,8 @@ import org.springframework.vault.util.IntegrationTestSupport;
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
@Autowired private VaultOperations vaultOperations;
|
||||
@Autowired
|
||||
private VaultOperations vaultOperations;
|
||||
private VaultTransitOperations transitOperations;
|
||||
|
||||
@Before
|
||||
@@ -53,12 +56,17 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport
|
||||
}
|
||||
|
||||
try {
|
||||
transitOperations.configureKey("mykey", VaultTransitKeyConfiguration.builder().deletionAllowed(true).build());
|
||||
} catch (Exception e) {}
|
||||
transitOperations.configureKey("mykey", VaultTransitKeyConfiguration
|
||||
.builder().deletionAllowed(true).build());
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
|
||||
try {
|
||||
transitOperations.deleteKey("mykey");
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -109,7 +117,8 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport
|
||||
try {
|
||||
transitOperations.deleteKey("hello-world");
|
||||
fail("Missing VaultException");
|
||||
} catch (VaultException e) {
|
||||
}
|
||||
catch (VaultException e) {
|
||||
assertThat(e).hasMessageContaining("Status 400");
|
||||
}
|
||||
}
|
||||
@@ -118,7 +127,8 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport
|
||||
public void deleteKeyShouldDeleteKey() throws Exception {
|
||||
|
||||
transitOperations.createKey("mykey");
|
||||
transitOperations.configureKey("mykey", VaultTransitKeyConfiguration.builder().deletionAllowed(true).build());
|
||||
transitOperations.configureKey("mykey", VaultTransitKeyConfiguration.builder()
|
||||
.deletionAllowed(true).build());
|
||||
transitOperations.deleteKey("mykey");
|
||||
|
||||
assertThat(transitOperations.getKey("mykey")).isNull();
|
||||
@@ -136,14 +146,16 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport
|
||||
@Test
|
||||
public void encryptShouldCreateCiphertextWithNonceAndContext() throws Exception {
|
||||
|
||||
transitOperations.createKey("mykey",
|
||||
VaultTransitKeyCreationRequest.builder().convergentEncryption(true).derived(true).build());
|
||||
transitOperations.createKey("mykey", VaultTransitKeyCreationRequest.builder()
|
||||
.convergentEncryption(true).derived(true).build());
|
||||
|
||||
VaultTransitContext transitRequest = VaultTransitContext.builder().context("blubb".getBytes()) //
|
||||
VaultTransitContext transitRequest = VaultTransitContext.builder()
|
||||
.context("blubb".getBytes()) //
|
||||
.nonce("123456789012".getBytes()) //
|
||||
.build();
|
||||
|
||||
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(), transitRequest);
|
||||
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(),
|
||||
transitRequest);
|
||||
assertThat(ciphertext).startsWith("vault:v1:");
|
||||
}
|
||||
|
||||
@@ -161,15 +173,16 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport
|
||||
@Test
|
||||
public void decryptShouldCreatePlaintextWithNonceAndContext() throws Exception {
|
||||
|
||||
transitOperations.createKey("mykey",
|
||||
VaultTransitKeyCreationRequest.builder().convergentEncryption(true).derived(true).build());
|
||||
transitOperations.createKey("mykey", VaultTransitKeyCreationRequest.builder()
|
||||
.convergentEncryption(true).derived(true).build());
|
||||
|
||||
VaultTransitContext transitRequest = VaultTransitContext.builder() //
|
||||
.context("blubb".getBytes()) //
|
||||
.nonce("123456789012".getBytes()) //
|
||||
.build();
|
||||
|
||||
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(), transitRequest);
|
||||
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(),
|
||||
transitRequest);
|
||||
|
||||
byte[] plaintext = transitOperations.decrypt("mykey", ciphertext, transitRequest);
|
||||
assertThat(new String(plaintext)).isEqualTo("hello-world");
|
||||
@@ -189,17 +202,19 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encryptAndRewrapShouldCreateCiphertextWithNonceAndContext() throws Exception {
|
||||
public void encryptAndRewrapShouldCreateCiphertextWithNonceAndContext()
|
||||
throws Exception {
|
||||
|
||||
transitOperations.createKey("mykey",
|
||||
VaultTransitKeyCreationRequest.builder().convergentEncryption(true).derived(true).build());
|
||||
transitOperations.createKey("mykey", VaultTransitKeyCreationRequest.builder()
|
||||
.convergentEncryption(true).derived(true).build());
|
||||
|
||||
VaultTransitContext transitRequest = VaultTransitContext.builder() //
|
||||
.context("blubb".getBytes()) //
|
||||
.nonce("123456789012".getBytes()) //
|
||||
.build();
|
||||
|
||||
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(), transitRequest);
|
||||
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(),
|
||||
transitRequest);
|
||||
transitOperations.rotate("mykey");
|
||||
|
||||
String rewrapped = transitOperations.rewrap("mykey", ciphertext, transitRequest);
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.core.env;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -25,9 +22,13 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.vault.core.VaultTemplate;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link VaultPropertySource}.
|
||||
*
|
||||
@@ -36,7 +37,8 @@ import org.springframework.vault.support.VaultResponse;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class VaultPropertySourceUnitTests {
|
||||
|
||||
@Mock VaultTemplate vaultTemplate;
|
||||
@Mock
|
||||
VaultTemplate vaultTemplate;
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldRejectEmptyPath() throws Exception {
|
||||
@@ -54,7 +56,8 @@ public class VaultPropertySourceUnitTests {
|
||||
|
||||
prepareResponse();
|
||||
|
||||
VaultPropertySource vaultPropertySource = new VaultPropertySource("hello", vaultTemplate, "secret/myapp");
|
||||
VaultPropertySource vaultPropertySource = new VaultPropertySource("hello",
|
||||
vaultTemplate, "secret/myapp");
|
||||
|
||||
assertThat(vaultPropertySource.getProperty("key")).isEqualTo("value");
|
||||
assertThat(vaultPropertySource.getProperty("integer")).isEqualTo("1");
|
||||
@@ -65,7 +68,8 @@ public class VaultPropertySourceUnitTests {
|
||||
|
||||
prepareResponse();
|
||||
|
||||
VaultPropertySource vaultPropertySource = new VaultPropertySource("hello", vaultTemplate, "secret/myapp");
|
||||
VaultPropertySource vaultPropertySource = new VaultPropertySource("hello",
|
||||
vaultTemplate, "secret/myapp");
|
||||
|
||||
assertThat(vaultPropertySource.getPropertyNames()).contains("key", "integer");
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ public class VaultApp {
|
||||
|
||||
vaultTemplate.write("secret/myapp", secrets);
|
||||
|
||||
VaultResponseSupport<Secrets> response = vaultTemplate.read("secret/myapp", Secrets.class);
|
||||
VaultResponseSupport<Secrets> response = vaultTemplate.read("secret/myapp",
|
||||
Secrets.class);
|
||||
System.out.println(response.getData().getUsername());
|
||||
|
||||
vaultTemplate.delete("secret/myapp");
|
||||
|
||||
@@ -15,18 +15,17 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CertificateBundle}.
|
||||
@@ -40,10 +39,11 @@ public class CertificateBundleUnitTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
Map<String, String> data = new ObjectMapper().readValue(getClass().getResource("/certificate.json"), Map.class);
|
||||
Map<String, String> data = new ObjectMapper().readValue(
|
||||
getClass().getResource("/certificate.json"), Map.class);
|
||||
|
||||
certificateBundle = CertificateBundle.of(data.get("serial_number"), data.get("certificate"), data.get("issuing_ca"),
|
||||
data.get("private_key"));
|
||||
certificateBundle = CertificateBundle.of(data.get("serial_number"),
|
||||
data.get("certificate"), data.get("issuing_ca"), data.get("private_key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -61,7 +61,8 @@ public class CertificateBundleUnitTests {
|
||||
|
||||
X509Certificate x509Certificate = certificateBundle.getX509Certificate();
|
||||
|
||||
assertThat(x509Certificate.getSubjectDN().getName()).isEqualTo("CN=hello.example.com");
|
||||
assertThat(x509Certificate.getSubjectDN().getName()).isEqualTo(
|
||||
"CN=hello.example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -69,7 +70,8 @@ public class CertificateBundleUnitTests {
|
||||
|
||||
X509Certificate x509Certificate = certificateBundle.getX509IssuerCertificate();
|
||||
|
||||
assertThat(x509Certificate.getSubjectDN().getName()).startsWith("CN=Intermediate CA Certificate");
|
||||
assertThat(x509Certificate.getSubjectDN().getName()).startsWith(
|
||||
"CN=Intermediate CA Certificate");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link VaultCertificateRequest}.
|
||||
*
|
||||
@@ -34,7 +34,8 @@ public class VaultCertificateRequestUnitTests {
|
||||
@Test
|
||||
public void shouldBuildRequestWithCommonName() throws Exception {
|
||||
|
||||
VaultCertificateRequest request = VaultCertificateRequest.builder().commonName("hello.com").build();
|
||||
VaultCertificateRequest request = VaultCertificateRequest.builder()
|
||||
.commonName("hello.com").build();
|
||||
|
||||
assertThat(request.getCommonName()).isEqualTo("hello.com");
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ import org.junit.Rule;
|
||||
*/
|
||||
public abstract class IntegrationTestSupport {
|
||||
|
||||
@Rule public final VaultRule vaultRule = new VaultRule();
|
||||
@Rule
|
||||
public final VaultRule vaultRule = new VaultRule();
|
||||
|
||||
public final PrepareVault prepare() {
|
||||
return vaultRule.prepare();
|
||||
|
||||
@@ -30,7 +30,8 @@ import org.springframework.vault.support.VaultTokenResponse;
|
||||
import org.springframework.vault.support.VaultUnsealStatus;
|
||||
|
||||
/**
|
||||
* Vault preparation utility class. This class allows preparing Vault for integration tests.
|
||||
* Vault preparation utility class. This class allows preparing Vault for integration
|
||||
* tests.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -59,12 +60,13 @@ public class PrepareVault {
|
||||
int createKeys = 2;
|
||||
int requiredKeys = 2;
|
||||
|
||||
VaultInitializationResponse initialized = vaultOperations.opsForSys()
|
||||
.initialize(VaultInitializationRequest.create(createKeys, requiredKeys));
|
||||
VaultInitializationResponse initialized = vaultOperations.opsForSys().initialize(
|
||||
VaultInitializationRequest.create(createKeys, requiredKeys));
|
||||
|
||||
for (int i = 0; i < requiredKeys; i++) {
|
||||
|
||||
VaultUnsealStatus unsealStatus = vaultOperations.opsForSys().unseal(initialized.getKeys().get(i));
|
||||
VaultUnsealStatus unsealStatus = vaultOperations.opsForSys().unseal(
|
||||
initialized.getKeys().get(i));
|
||||
|
||||
if (!unsealStatus.isSealed()) {
|
||||
break;
|
||||
@@ -90,7 +92,8 @@ public class PrepareVault {
|
||||
tokenRequest.setPolicies(Collections.singletonList(policy));
|
||||
}
|
||||
|
||||
VaultTokenResponse vaultTokenResponse = vaultOperations.opsForToken().create(tokenRequest);
|
||||
VaultTokenResponse vaultTokenResponse = vaultOperations.opsForToken().create(
|
||||
tokenRequest);
|
||||
return vaultTokenResponse.getToken();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.springframework.vault.util;
|
||||
import java.io.File;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
/**
|
||||
* Utility to retrieve settings during test.
|
||||
@@ -35,7 +35,8 @@ public class Settings {
|
||||
|
||||
File workDir = findWorkDir();
|
||||
|
||||
return SslConfiguration.forTrustStore(new FileSystemResource(new File(workDir, "keystore.jks")), "changeit");
|
||||
return SslConfiguration.forTrustStore(new FileSystemResource(new File(workDir,
|
||||
"keystore.jks")), "changeit");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,8 +50,8 @@ public class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the {@code work} directory, starting at the given {@code directory}. Search
|
||||
* is performed by walking the parent directories.
|
||||
* Find the {@code work} directory, starting at the given {@code directory}. Search is
|
||||
* performed by walking the parent directories.
|
||||
* @return the {@link File} pointing to the {@code work} directory
|
||||
* @throws IllegalStateException If the {@code work} directory cannot be found.
|
||||
*/
|
||||
|
||||
@@ -32,9 +32,10 @@ import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Factory for {@link RestTemplate}. The template caches the {@link ClientHttpRequestFactory} once it was initialized.
|
||||
* Changes to timeouts or the SSL configuration won't be applied once a {@link ClientHttpRequestFactory} was created for
|
||||
* the first time.
|
||||
* Factory for {@link RestTemplate}. The template caches the
|
||||
* {@link ClientHttpRequestFactory} once it was initialized. Changes to timeouts or the
|
||||
* SSL configuration won't be applied once a {@link ClientHttpRequestFactory} was created
|
||||
* for the first time.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -43,9 +44,10 @@ public class TestRestTemplateFactory {
|
||||
private static final AtomicReference<ClientHttpRequestFactory> factoryCache = new AtomicReference<ClientHttpRequestFactory>();
|
||||
|
||||
/**
|
||||
* Create a new {@link RestTemplate} using the {@link SslConfiguration}. The underlying
|
||||
* {@link ClientHttpRequestFactory} is cached. See {@link #create(ClientHttpRequestFactory)} to create
|
||||
* {@link RestTemplate} for a given {@link ClientHttpRequestFactory}.
|
||||
* Create a new {@link RestTemplate} using the {@link SslConfiguration}. The
|
||||
* underlying {@link ClientHttpRequestFactory} is cached. See
|
||||
* {@link #create(ClientHttpRequestFactory)} to create {@link RestTemplate} for a
|
||||
* given {@link ClientHttpRequestFactory}.
|
||||
*
|
||||
* @param sslConfiguration must not be {@literal null}.
|
||||
* @return
|
||||
@@ -57,15 +59,18 @@ public class TestRestTemplateFactory {
|
||||
try {
|
||||
initializeClientHttpRequestFactory(sslConfiguration);
|
||||
return create(factoryCache.get());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link RestTemplate} using the {@link ClientHttpRequestFactory}. The {@link RestTemplate} will throw
|
||||
* {@link org.springframework.web.client.HttpStatusCodeException exceptions} in error cases and behave in that aspect
|
||||
* like the regular {@link org.springframework.web.client.RestTemplate}.
|
||||
* Create a new {@link RestTemplate} using the {@link ClientHttpRequestFactory}. The
|
||||
* {@link RestTemplate} will throw
|
||||
* {@link org.springframework.web.client.HttpStatusCodeException exceptions} in error
|
||||
* cases and behave in that aspect like the regular
|
||||
* {@link org.springframework.web.client.RestTemplate}.
|
||||
*
|
||||
* @param requestFactory must not be {@literal null}.
|
||||
* @return
|
||||
@@ -78,8 +83,8 @@ public class TestRestTemplateFactory {
|
||||
template.setRequestFactory(requestFactory);
|
||||
template.getInterceptors().add(new ClientHttpRequestInterceptor() {
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
|
||||
throws IOException {
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution) throws IOException {
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
});
|
||||
@@ -87,7 +92,8 @@ public class TestRestTemplateFactory {
|
||||
return template;
|
||||
}
|
||||
|
||||
private static void initializeClientHttpRequestFactory(SslConfiguration sslConfiguration) throws Exception {
|
||||
private static void initializeClientHttpRequestFactory(
|
||||
SslConfiguration sslConfiguration) throws Exception {
|
||||
|
||||
if (factoryCache.get() != null) {
|
||||
return;
|
||||
@@ -104,17 +110,19 @@ public class TestRestTemplateFactory {
|
||||
|
||||
if (clientHttpRequestFactory instanceof DisposableBean) {
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread("ClientHttpRequestFactory Shutdown Hook") {
|
||||
Runtime.getRuntime().addShutdownHook(
|
||||
new Thread("ClientHttpRequestFactory Shutdown Hook") {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
((DisposableBean) clientHttpRequestFactory).destroy();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
((DisposableBean) clientHttpRequestFactory).destroy();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.junit.rules.ExternalResource;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.authentication.SessionManager;
|
||||
import org.springframework.vault.client.VaultClient;
|
||||
@@ -54,7 +55,8 @@ public class VaultRule extends ExternalResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link VaultRule} with the given {@link SslConfiguration} and {@link VaultEndpoint}.
|
||||
* Create a new {@link VaultRule} with the given {@link SslConfiguration} and
|
||||
* {@link VaultEndpoint}.
|
||||
*
|
||||
* @param sslConfiguration must not be {@literal null}.
|
||||
* @param vaultEndpoint must not be {@literal null}.
|
||||
@@ -64,10 +66,13 @@ public class VaultRule extends ExternalResource {
|
||||
Assert.notNull(sslConfiguration, "SslConfiguration must not be null");
|
||||
Assert.notNull(vaultEndpoint, "VaultEndpoint must not be null");
|
||||
|
||||
VaultClient vaultClient = new VaultClient(TestRestTemplateFactory.create(sslConfiguration), vaultEndpoint);
|
||||
DefaultVaultClientFactory clientFactory = new DefaultVaultClientFactory(vaultClient);
|
||||
VaultClient vaultClient = new VaultClient(
|
||||
TestRestTemplateFactory.create(sslConfiguration), vaultEndpoint);
|
||||
DefaultVaultClientFactory clientFactory = new DefaultVaultClientFactory(
|
||||
vaultClient);
|
||||
|
||||
VaultTemplate vaultTemplate = new VaultTemplate(clientFactory, new PreparingSessionManager());
|
||||
VaultTemplate vaultTemplate = new VaultTemplate(clientFactory,
|
||||
new PreparingSessionManager());
|
||||
|
||||
this.token = Settings.token();
|
||||
this.prepareVault = new PrepareVault(vaultClient, vaultTemplate);
|
||||
@@ -82,18 +87,24 @@ public class VaultRule extends ExternalResource {
|
||||
|
||||
socket = new Socket();
|
||||
|
||||
socket.connect(new InetSocketAddress(InetAddress.getByName("localhost"), vaultEndpoint.getPort()));
|
||||
socket.connect(new InetSocketAddress(InetAddress.getByName("localhost"),
|
||||
vaultEndpoint.getPort()));
|
||||
socket.close();
|
||||
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Vault is not running on localhost:%d which is required to run a test using @Rule %s",
|
||||
String.format(
|
||||
"Vault is not running on localhost:%d which is required to run a test using @Rule %s",
|
||||
vaultEndpoint.getPort(), getClass().getSimpleName()));
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
handlers = org.slf4j.bridge.SLF4JBridgeHandler
|
||||
handlers=org.slf4j.bridge.SLF4JBridgeHandler
|
||||
|
||||
Reference in New Issue
Block a user