Polish and add JavaDoc.

This commit is contained in:
Scott Frederick
2017-04-21 18:32:27 -05:00
parent b5708f0df8
commit 75b06263de
50 changed files with 3420 additions and 1274 deletions

View File

@@ -0,0 +1,296 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<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.insert_space_after_comma_in_enum_declarations" 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.insert_space_before_at_in_annotation_type_declaration" 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_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.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.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.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.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_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.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>

View 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

8
manifest.yml Normal file
View File

@@ -0,0 +1,8 @@
---
applications:
- name: spring-credhub-demo
memory: 1G
path: spring-credhub-demo/target/spring-credhub-demo-1.0.0.BUILD-SNAPSHOT.jar
env:
logging.level.org.apache.http.wire: DEBUG

View File

@@ -15,6 +15,7 @@
<modules>
<module>spring-credhub-dependencies</module>
<module>spring-credhub-core</module>
<module>spring-credhub-demo</module>
</modules>
<properties>

View File

@@ -74,13 +74,6 @@
<artifactId>json-path-matchers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -16,12 +16,18 @@
package org.springframework.credhub.configuration;
import java.io.IOException;
import java.security.GeneralSecurityException;
import javax.net.ssl.SSLContext;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.springframework.credhub.support.ClientOptions;
import org.springframework.credhub.support.SslConfiguration;
import org.springframework.http.client.ClientHttpRequestFactory;
@@ -29,17 +35,13 @@ import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.GeneralSecurityException;
/**
* 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 Scott Frederick
* @author Mark Paluch
* @author Scott Frederick
*/
public class ClientHttpRequestFactoryFactory {
@@ -51,13 +53,13 @@ public class ClientHttpRequestFactoryFactory {
* Create a {@link ClientHttpRequestFactory} for the given {@link ClientOptions} and
* {@link SslConfiguration}.
*
* @param options must not be {@literal null}
* @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.
*/
public static ClientHttpRequestFactory create(ClientOptions options,
SslConfiguration sslConfiguration) {
SslConfiguration sslConfiguration) {
Assert.notNull(options, "ClientOptions must not be null");
Assert.notNull(sslConfiguration, "SslConfiguration must not be null");
@@ -66,9 +68,11 @@ public class ClientHttpRequestFactoryFactory {
if (HTTP_COMPONENTS_PRESENT) {
return HttpComponents.usingHttpComponents(options, sslConfiguration);
}
} catch (GeneralSecurityException e) {
}
catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
}
catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -85,18 +89,22 @@ public class ClientHttpRequestFactoryFactory {
*/
static class HttpComponents {
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options, SslConfiguration sslConfiguration)
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options,
SslConfiguration sslConfiguration)
throws GeneralSecurityException, IOException {
HttpClientBuilder httpClientBuilder = HttpClients.custom();
if (hasSslConfiguration(sslConfiguration)) {
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(sslConfiguration.getKeyStore(), new TrustSelfSignedStrategy())
.loadKeyMaterial(sslConfiguration.getTrustStore(), sslConfiguration.getKeyPassword())
.loadTrustMaterial(sslConfiguration.getKeyStore(),
new TrustSelfSignedStrategy())
.loadKeyMaterial(sslConfiguration.getTrustStore(),
sslConfiguration.getKeyPassword())
.build();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
sslContext);
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
httpClientBuilder.setSSLContext(sslContext);
}

View File

@@ -27,18 +27,53 @@ import org.springframework.credhub.support.ClientOptions;
import org.springframework.credhub.support.SslConfiguration;
import org.springframework.http.client.ClientHttpRequestFactory;
/**
* Configuration for the {@link CredHubTemplate} used to communicate with CredHub. This
* class is typically imported into Java-based Spring application configuration as in
* this example:
*
* <pre>
* {@code
* &#64;Configuration
* &#64;Import(CredHubConfiguration.class)
* public class MyConfiguration {
* }
* }
* </pre>
*
* @author Scott Frederick
*/
@Configuration
public class CredHubConfiguration {
/**
* Create the {@link CredHubProperties} that contains information about the
* CredHub server.
*
* @return the {@link CredHubProperties} bean
*/
@Bean
public CredHubProperties credHubProperties() {
return new CredHubProperties();
}
/**
* Create the {@link CloudFoundryAppInstanceProperties} that contains information
* about the application instance running on Cloud Foundry.
*
* @return the {@link CloudFoundryAppInstanceProperties} bean
*/
@Bean
public CloudFoundryAppInstanceProperties cloudFoundryAppInstanceProperties() {
return new CloudFoundryAppInstanceProperties();
}
/**
* Create the {@link CredHubTemplate} that the application will use to interact
* with CredHub.
*
* @return the {@link CredHubTemplate} bean
*/
@Bean
public CredHubTemplate credHubTemplate() {
return new CredHubTemplate(credHubProperties().getApiUriBase(),
@@ -46,11 +81,11 @@ public class CredHubConfiguration {
}
/**
* 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.
* 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.
@@ -65,20 +100,26 @@ public class CredHubConfiguration {
}
/**
* @return {@link ClientOptions} to configure communication parameters.
* @see ClientOptions
* Create the default {@link ClientOptions} to configure communication parameters.
*
* @return the default {@link ClientOptions}
*/
private ClientOptions clientOptions() {
return new ClientOptions();
}
/**
* @return SSL configuration options.
* @see SslConfiguration
* Create the default {@link SslConfiguration} to configure SSL context parameters.
* The default configuration uses a certificate and key supplied in the application
* container to configure mutual SSL authentication between the client application
* and the CredHub server.
*
* @return the default {@link SslConfiguration}
*/
private SslConfiguration sslConfiguration() {
CloudFoundryAppInstanceProperties properties = cloudFoundryAppInstanceProperties();
return SslConfiguration.forContainerCert(properties.getInstanceCertLocation(), properties.getInstanceKeyLocation());
return SslConfiguration.forContainerCert(properties.getInstanceCertLocation(),
properties.getInstanceKeyLocation());
}
/**

View File

@@ -18,6 +18,12 @@ package org.springframework.credhub.core;
import org.springframework.beans.factory.annotation.Value;
/**
* Properties containing information about an application instance
* running on Cloud Foundry.
*
* @author Scott Frederick
*/
public class CloudFoundryAppInstanceProperties {
@Value("${CF_INSTANCE_CERT}")
private String instanceCertLocation;
@@ -25,18 +31,41 @@ public class CloudFoundryAppInstanceProperties {
@Value("${CF_INSTANCE_KEY}")
private String instanceKeyLocation;
/**
* Create a new instance without initializing properties.
*/
public CloudFoundryAppInstanceProperties() {
}
public CloudFoundryAppInstanceProperties(String instanceCertLocation, String instanceKeyLocation) {
/**
* Create a new instance from the provided property values. Intended to be used
* internally for testing.
*
* @param instanceCertLocation the absolute path of the certificate file in the app
* instance container
* @param instanceKeyLocation the absolute path of the private key file in the app
* instance container
*/
CloudFoundryAppInstanceProperties(String instanceCertLocation,
String instanceKeyLocation) {
this.instanceCertLocation = instanceCertLocation;
this.instanceKeyLocation = instanceKeyLocation;
}
/**
* Get the absolute path of the certificate file in the app instance container.
*
* @return the certificate file path
*/
public String getInstanceCertLocation() {
return instanceCertLocation;
}
/**
* Get the absolute path of the private key file in the app instance container.
*
* @return the key file path
*/
public String getInstanceKeyLocation() {
return instanceKeyLocation;
}

View File

@@ -18,21 +18,73 @@
package org.springframework.credhub.core;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriTemplateHandler;
import org.springframework.web.util.UriTemplateHandler;
/**
* Factory for creating a {@link RestTemplate} configured for communication with
* a CredHub server.
*
* @author Scott Frederick
*/
public class CredHubClient {
public static RestTemplate createRestTemplate(String baseUri, ClientHttpRequestFactory clientHttpRequestFactory) {
/**
* Create a {@link RestTemplate} configured for communication with a CredHub server.
*
* @param baseUri the base URI for the CredHub server
* @param clientHttpRequestFactory the {@link ClientHttpRequestFactory} to use when
* creating new connections
* @return a configured {@link RestTemplate}
*/
public static RestTemplate createRestTemplate(String baseUri,
ClientHttpRequestFactory clientHttpRequestFactory) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(createUriTemplateHandler(baseUri));
restTemplate.setRequestFactory(clientHttpRequestFactory);
restTemplate.setUriTemplateHandler(createUriTemplateHandler(baseUri));
restTemplate.setMessageConverters(createMessageConverters());
return restTemplate;
}
/**
* Create a {@link UriTemplateHandler} that prefixes all {@link RestTemplate} calls
* with the configured {@literal baseUri}.
*
* @param baseUri the base URI for the CredHub server
* @return a configured {@link UriTemplateHandler}
*/
private static DefaultUriTemplateHandler createUriTemplateHandler(String baseUri) {
DefaultUriTemplateHandler uriTemplateHandler = new DefaultUriTemplateHandler();
uriTemplateHandler.setBaseUrl(baseUri);
return uriTemplateHandler;
}
/**
* Create the {@link HttpMessageConverter}s necessary to build request to
* and parse responses from CredHub.
*
* @return the list of {@link HttpMessageConverter}s
*/
private static List<HttpMessageConverter<?>> createMessageConverters() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new ISO8601DateFormat());
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>(3);
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new MappingJackson2HttpMessageConverter(objectMapper));
return messageConverters;
}
}

View File

@@ -20,16 +20,30 @@ import org.springframework.core.NestedRuntimeException;
import org.springframework.http.HttpStatus;
import org.springframework.web.client.HttpStatusCodeException;
/**
* Exception class to capture errors specific to CredHub communication.
*
* @author Scott Frederick
*/
public class CredHubException extends NestedRuntimeException {
/**
* Create a new exception with the provided root cause.
*
* @param e an {@link HttpStatusCodeException} caught while attempting to communicate
* with CredHub
*/
public CredHubException(HttpStatusCodeException e) {
super("Error calling CredHub: " + e.getStatusCode() + ": " + e.getResponseBodyAsString());
super("Error calling CredHub: " + e.getStatusCode() + ": "
+ e.getResponseBodyAsString());
}
/**
* Create a new exception with the provided error status code.
*
* @param statusCode an {@link HttpStatus} indicating an error while attempting to
* communicate with CredHub
*/
public CredHubException(HttpStatus statusCode) {
super("Error calling CredHub: " + statusCode);
}
public CredHubException(String message) {
super("Error returned from call to CredHub: " + message);
}
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import java.util.List;
import java.util.Map;
import org.springframework.credhub.support.CredentialDetails;
import org.springframework.credhub.support.CredentialName;
import org.springframework.credhub.support.CredentialSummary;
import org.springframework.credhub.support.WriteRequest;
import org.springframework.web.client.RestTemplate;
/**
* Specifies the main interaction with CredHub to save, retrieve,
* and delete credentials.
*
* @author Scott Frederick
*/
public interface CredHubOperations {
/**
* Write a new credential to CredHub, or overwrite an existing credential with a new
* value.
*
* @param writeRequest the credential to write to CredHub; must not be {@literal null}
* @return the details of the written credential
*/
CredentialDetails write(WriteRequest writeRequest);
/**
* Retrieve a credential using its ID, as returned in a write request.
*
* @param id the ID of the credential; must not be {@literal null}
* @return the details of the retrieved credential
*/
CredentialDetails getById(String id);
/**
* Retrieve a credential using its name, as passed to a write request.
* A collection of all stored values for the named credential will be returned,
* including historical values.
*
* @param name the name of the credential; must not be {@literal null}
* @return the details of the retrieved credential, including history
*/
List<CredentialDetails> getByName(String name);
/**
* Retrieve a credential using its name, as passed to a write request.
* A collection of all stored values for the named credential will be returned,
* including historical values.
*
* @param name the name of the credential; must not be {@literal null}
* @return the details of the retrieved credential, including history
*/
List<CredentialDetails> getByName(CredentialName name);
/**
* Find a credential using a full or partial name.
*
* @param name the name of the credential; must not be {@literal null}
* @return a summary of the credential search results
*/
List<CredentialSummary> findByName(String name);
/**
* Find a credential using a full or partial name.
*
* @param name the name of the credential; must not be {@literal null}
* @return a summary of the credential search results
*/
List<CredentialSummary> findByName(CredentialName name);
/**
* Find a credential using a path.
*
* @param path the path to the credential; must not be {@literal null}
* @return a summary of the credential search results
*/
List<CredentialSummary> findByPath(String path);
/**
* Delete a credential by its full name.
*
* @param name the name of the credential; must not be {@literal null}
*/
void deleteByName(String name);
/**
* Delete a credential by its full name.
*
* @param name the name of the credential; must not be {@literal null}
*/
void deleteByName(CredentialName name);
/**
* Search the provided data structure of bound service credentials, looking for
* references to CredHub credentials. Any CredHub credentials found in the data
* structure will be replaced by the credential value stored in CredHub.
*
* Example:
*
* A JSON data structure parsed from a {@literal VCAP_SERVICES} environment
* variable might look like this if the service broker that provided the binding
* is integrated with CredHub:
*
* <pre>
* {@code
* {
* "service-offering": [{
* "credentials": {
* "credhub-ref": "((/c/service-broker/service-offering/1111-2222-3333-4444/credentials))"
* }
* "label": "service-offering",
* "name": "service-instance",
* "plan": "standard",
* "tags": ["
* "cloud-service"
* ]
* }]
* }
* }
* </pre>
*
* Assuming that CredHub has a credential with the name
* {@literal /c/service-broker/service-offering/1111-2222-3333-4444/credentials},
* passing the data structure above to this method would result in the
* {@literal credhub-ref} field being replaced by the credentials stored in CredHub:
*
* <pre>
* {@code
* {
* "service-offering": [{
* "credentials": {
* "url": "https://servicehost.example.com/",
* "username": "someuser",
* "password": "secret"
* }
* "label": "service-offering",
* "name": "service-instance",
* "plan": "standard",
* "tags": ["
* "cloud-service"
* ]
* }]
* }
* }
* </pre>
*
* @param serviceData a data structure of bound service credentials, as would be
* parsed from the {@literal VCAP_SERVICES} environment variable provided to
* applications running on Cloud Foundry
* @return the serviceData structure with CredHub references replaced by stored
* credential values
*/
Map<String, Object> interpolateServiceData(Map<String, Object> serviceData);
/**
* Allow interaction with the configured {@link RestTemplate} not provided
* by other methods.
*
* @param callback wrapper for the callback method
* @return the return value from the callback method
*/
<T> T doWithRest(RestOperationsCallback<T> callback);
}

View File

@@ -20,17 +20,37 @@ package org.springframework.credhub.core;
import org.springframework.beans.factory.annotation.Value;
/**
* Properties containing information about a CredHub server.
*
* @author Scott Frederick
*/
public class CredHubProperties {
@Value("${CREDHUB_API}")
private String apiUriBase;
/**
* Create a new instance without initializing properties.
*/
public CredHubProperties() {
}
public CredHubProperties(String apiUriBase) {
/**
* Create a new instance with the provided properties. Intended to be used
* internally for testing.
*
* @param apiUriBase the base URI for the CredHub server
*/
CredHubProperties(String apiUriBase) {
this.apiUriBase = apiUriBase;
}
/**
* Get the base URI for the CredHub server (scheme, host, and port). This value
* will be prepended to all requests to CredHub.
*
* @return the base URI
*/
public String getApiUriBase() {
return apiUriBase;
}

View File

@@ -1,9 +1,31 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import org.springframework.credhub.support.CredHubResponse;
import org.springframework.credhub.support.CredentialDataResponse;
import org.springframework.credhub.support.CredentialData;
import org.springframework.credhub.support.FindResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.credhub.support.CredentialDetails;
import org.springframework.credhub.support.CredentialDetailsData;
import org.springframework.credhub.support.CredentialName;
import org.springframework.credhub.support.CredentialSummary;
import org.springframework.credhub.support.CredentialSummaryData;
import org.springframework.credhub.support.WriteRequest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
@@ -15,59 +37,65 @@ import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
public class CredHubTemplate {
/**
* Implements the main interaction with CredHub to save, retrieve,
* and delete credentials.
*
* @author Scott Frederick
*/
public class CredHubTemplate implements CredHubOperations {
static final String BASE_URL_PATH = "/api/v1/data";
static final String ID_URL_PATH = BASE_URL_PATH + "/{id}";
static final String NAME_URL_QUERY = BASE_URL_PATH + "?name={name}";
static final String NAME_LIKE_URL_QUERY = BASE_URL_PATH + "?name-like={name}";
static final String PATH_URL_QUERY = BASE_URL_PATH + "?path={path}";
static final String INTERPOLATE_URL_PATH = "/api/v1/vcap";
static final String VCAP_SERVICES_KEY = "VCAP_SERVICES";
private final RestTemplate restTemplate;
/**
* Create a new {@link CredHubTemplate} using the provided {@link RestTemplate}.
* Intended for internal testing only.
*
* @param restTemplate the {@link RestTemplate} to use for interactions with CredHub
*/
CredHubTemplate(RestTemplate restTemplate) {
Assert.notNull(restTemplate, "restTemplate must not be null");
this.restTemplate = restTemplate;
}
/**
* Create a new {@link CredHubTemplate} using the provided base URI and
* {@link ClientHttpRequestFactory}.
*
* @param apiUriBase the base URI for the CredHub server (scheme, host, and port);
* must not be {@literal null}
* @param clientHttpRequestFactory the {@link ClientHttpRequestFactory} to use when
* creating new connections
*/
public CredHubTemplate(String apiUriBase, ClientHttpRequestFactory clientHttpRequestFactory) {
this.restTemplate = CredHubClient.createRestTemplate(apiUriBase, clientHttpRequestFactory);
Assert.notNull(apiUriBase, "apiUriBase must not be null");
Assert.notNull(clientHttpRequestFactory, "clientHttpRequestFactory must not be null");
this.restTemplate = CredHubClient.createRestTemplate(apiUriBase,
clientHttpRequestFactory);
}
public CredentialData write(final WriteRequest writeRequest) {
return doWithRest(new RestOperationsCallback<CredentialData>() {
@Override
public CredentialDetails write(final WriteRequest writeRequest) {
Assert.notNull(writeRequest, "writeRequest must not be null");
return doWithRest(new RestOperationsCallback<CredentialDetails>() {
@Override
public CredentialData doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDataResponse> response =
restOperations.exchange(BASE_URL_PATH, HttpMethod.PUT,
public CredentialDetails doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialDetails> response = restOperations
.exchange(BASE_URL_PATH, HttpMethod.PUT,
new HttpEntity<WriteRequest>(writeRequest),
CredentialDataResponse.class);
throwExceptionOnError(response);
return response.getBody().getData().get(0);
}
});
}
public CredentialData getById(final String id) {
return doWithRest(new RestOperationsCallback<CredentialData>() {
@Override
public CredentialData doWithRestOperations(RestOperations restOperations) {
ResponseEntity<CredentialDataResponse> response =
restOperations.getForEntity(ID_URL_PATH, CredentialDataResponse.class, id);
throwExceptionOnError(response);
return response.getBody().getData().get(0);
}
});
}
public FindResponse findByName(final String name) {
return doWithRest(new RestOperationsCallback<FindResponse>() {
@Override
public FindResponse doWithRestOperations(RestOperations restOperations) {
ResponseEntity<FindResponse> response =
restOperations.getForEntity(NAME_LIKE_URL_QUERY, FindResponse.class, name);
CredentialDetails.class);
throwExceptionOnError(response);
@@ -76,12 +104,16 @@ public class CredHubTemplate {
});
}
public FindResponse findByPath(final String path) {
return doWithRest(new RestOperationsCallback<FindResponse>() {
@Override
public CredentialDetails getById(final String id) {
Assert.notNull(id, "credential id must not be null");
return doWithRest(new RestOperationsCallback<CredentialDetails>() {
@Override
public FindResponse doWithRestOperations(RestOperations restOperations) {
ResponseEntity<FindResponse> response =
restOperations.getForEntity(PATH_URL_QUERY, FindResponse.class, path);
public CredentialDetails doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialDetails> response = restOperations
.getForEntity(ID_URL_PATH, CredentialDetails.class, id);
throwExceptionOnError(response);
@@ -90,7 +122,81 @@ public class CredHubTemplate {
});
}
@Override
public List<CredentialDetails> getByName(final String name) {
Assert.notNull(name, "credential name must not be null");
return doWithRest(new RestOperationsCallback<List<CredentialDetails>>() {
@Override
public List<CredentialDetails> doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialDetailsData> response = restOperations
.getForEntity(NAME_URL_QUERY, CredentialDetailsData.class,
name);
throwExceptionOnError(response);
return response.getBody().getData();
}
});
}
@Override
public List<CredentialDetails> getByName(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
return getByName(name.getName());
}
@Override
public List<CredentialSummary> findByName(final String name) {
Assert.notNull(name, "credential name must not be null");
return doWithRest(new RestOperationsCallback<List<CredentialSummary>>() {
@Override
public List<CredentialSummary> doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialSummaryData> response = restOperations
.getForEntity(NAME_LIKE_URL_QUERY,
CredentialSummaryData.class, name);
throwExceptionOnError(response);
return response.getBody().getCredentials();
}
});
}
@Override
public List<CredentialSummary> findByName(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
return findByName(name.getName());
}
@Override
public List<CredentialSummary> findByPath(final String path) {
Assert.notNull(path, "credential path must not be null");
return doWithRest(new RestOperationsCallback<List<CredentialSummary>>() {
@Override
public List<CredentialSummary> doWithRestOperations(
RestOperations restOperations) {
ResponseEntity<CredentialSummaryData> response = restOperations
.getForEntity(PATH_URL_QUERY, CredentialSummaryData.class,
path);
throwExceptionOnError(response);
return response.getBody().getCredentials();
}
});
}
@Override
public void deleteByName(final String name) {
Assert.notNull(name, "credential name must not be null");
doWithRest(new RestOperationsCallback<Void>() {
@Override
public Void doWithRestOperations(RestOperations restOperations) {
@@ -100,23 +206,76 @@ public class CredHubTemplate {
});
}
@Override
public void deleteByName(final CredentialName name) {
Assert.notNull(name, "credential name must not be null");
deleteByName(name.getName());
}
@Override
public Map<String, Object> interpolateServiceData(final Map<String, Object> serviceData) {
Assert.notNull(serviceData, "serviceData must not be null");
return doWithRest(new RestOperationsCallback<Map<String, Object>>() {
@Override
public Map<String, Object> doWithRestOperations(RestOperations restOperations) {
Map<String, Map<String, Object>> wrappedServiceData = wrapServiceDataRequest(serviceData);
ResponseEntity<Map<String, Map<String, Object>>> response = restOperations
.exchange(INTERPOLATE_URL_PATH, HttpMethod.POST,
new HttpEntity<Map<String, Map<String, Object>>>(wrappedServiceData), mapType());
throwExceptionOnError(response);
return response.getBody().get(VCAP_SERVICES_KEY);
}
});
}
@Override
public <T> T doWithRest(RestOperationsCallback<T> callback) {
Assert.notNull(callback, "Callback must not be null");
Assert.notNull(callback, "callback must not be null");
try {
return callback.doWithRestOperations(restTemplate);
} catch (HttpStatusCodeException e) {
}
catch (HttpStatusCodeException e) {
throw new CredHubException(e);
}
}
private void throwExceptionOnError(ResponseEntity<? extends CredHubResponse> response) {
/**
* Wrap the service data structure with the "VCAP_SERVICES" key as required by the
* CredHub interpolation API.
*
* @param serviceData a {@literal Map} of services details
* @return the provided {@literal serviceData} structure wrapped with the "VCAP_SERVICES" key
*/
private Map<String, Map<String, Object>> wrapServiceDataRequest(Map<String, Object> serviceData) {
Map<String, Map<String, Object>> wrappedServiceData = new HashMap<String, Map<String, Object>>();
wrappedServiceData.put(VCAP_SERVICES_KEY, serviceData);
return wrappedServiceData;
}
/**
* Helper method to create a type reference for use by {@link RestTemplate}.
*
* @return the type reference for a {@literal Map} type
*/
private ParameterizedTypeReference<Map<String, Map<String, Object>>> mapType() {
return new ParameterizedTypeReference<Map<String, Map<String, Object>>>() {};
}
/**
* Helper method to throw an appropriate exception if a request to CredHub
* returns with an error code.
*
* @param response a {@link ResponseEntity} returned from {@link RestTemplate}
*/
private void throwExceptionOnError(ResponseEntity<?> response) {
if (!response.getStatusCode().equals(HttpStatus.OK)) {
throw new CredHubException(response.getStatusCode());
}
if (response.getBody().getErrorMessage() != null) {
throw new CredHubException(response.getBody().getErrorMessage());
}
}
}

View File

@@ -26,7 +26,8 @@ import org.springframework.web.client.RestOperations;
public interface RestOperationsCallback<T> {
/**
* Callback method providing a {@link RestOperations} that is configured to interact with the CredHub server.
* Callback method providing a {@link RestOperations} that is configured to interact
* with the CredHub server.
*
* @param restOperations restOperations to use, must not be {@literal null}.
* @return a result object or null if none.

View File

@@ -18,26 +18,54 @@
package org.springframework.credhub.support;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.Setter;
import lombok.Singular;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Data
@Builder
/**
* Access control requirements for a credential in CredHub. If provided when a
* credential is written, these values will control what actors can access update
* or retrieve the credential.
*
* This object of this type is typically constructed by the application and passed
* as part of a {@link WriteRequest}.
*
* @author Scott Frederick
*/
public class AccessControlEntry {
private static final String APP_ACTOR_PREFIX = "mtls-app:";
@Setter(AccessLevel.PRIVATE)
private String actor;
@Singular
private String actor;
private List<Operation> operations;
/**
* Create a set of access controls. Intended to be used internally for testing.
* Clients should use {@link #builder()} to construct instances of this class.
*
* @param actor the ID of the entity that will be allowed to access the credential
* @param operations the operations that the actor will be allowed to perform on the
* credential
*/
AccessControlEntry(String actor, List<Operation> operations) {
this.actor = actor;
this.operations = operations;
}
/**
* Get the ID of the entity that will be allowed to access the credential
*
* @return the ID
*/
public String getActor() {
return this.actor;
}
/**
* Get the set of operations that the actor will be allowed to perform on
* the credential.
*
* @return the operations
*/
public List<String> getOperations() {
List<String> operationValues = new ArrayList<String>(operations.size());
for (Operation operation : operations) {
@@ -46,13 +74,136 @@ public class AccessControlEntry {
return operationValues;
}
/**
* Create a builder that provides a fluent API for providing the values required
* to construct a {@link AccessControlEntry}.
*
* @return a builder
*/
public static AccessControlEntryBuilder builder() {
return new AccessControlEntryBuilder();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof AccessControlEntry))
return false;
AccessControlEntry that = (AccessControlEntry) o;
if (actor != null ? !actor.equals(that.actor) : that.actor != null)
return false;
return operations != null ? operations.equals(that.operations)
: that.operations == null;
}
@Override
public int hashCode() {
int result = actor != null ? actor.hashCode() : 0;
result = 31 * result + (operations != null ? operations.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "AccessControlEntry{"
+ "actor='" + actor + '\''
+ ", operations=" + operations
+ '}';
}
/**
* A builder that provides a fluent API for constructing {@link AccessControlEntry}
* instances.
*/
public static class AccessControlEntryBuilder {
private String actor;
private ArrayList<Operation> operations;
AccessControlEntryBuilder() {
}
/**
* Set the ID of an application that will be allowed to access a credential.
* This will often be a Cloud Foundry application GUID.
*
* @param appId application ID
* @return the builder
*/
public AccessControlEntryBuilder app(String appId) {
this.actor = APP_ACTOR_PREFIX + appId;
return this;
}
/**
* Set the name of an actor that will be allowed to access the credential.
*
* @param actor actor name
* @return the builder
*/
public AccessControlEntryBuilder actor(String actor) {
this.actor = actor;
return this;
}
/**
* Set an {@link Operation} that the actor will be allowed to perform on
* the credential. Multiple operations can be provided with consecutive calls to
* this method.
*
* @param operation the {@link Operation}
* @return the builder
*/
public AccessControlEntryBuilder operation(Operation operation) {
initOperations();
this.operations.add(operation);
return this;
}
/**
* Specify a set of {@link Operation}s that the actor will be allowed to perform
* on the credential.
*
* @param operations the {@link Operation}s
* @return the builder
*/
public AccessControlEntryBuilder operations(Collection<? extends Operation> operations) {
initOperations();
this.operations.addAll(operations);
return this;
}
private void initOperations() {
if (this.operations == null) this.operations = new ArrayList<Operation>();
}
/**
* Construct an {@link AccessControlEntry} with the provided values.
*
* @return an {@link AccessControlEntry}
*/
public AccessControlEntry build() {
List<Operation> operations;
switch (this.operations == null ? 0 : this.operations.size()) {
case 0:
operations = java.util.Collections.emptyList();
break;
case 1:
operations = java.util.Collections.singletonList(this.operations.get(0));
break;
default:
operations = java.util.Collections.unmodifiableList(new ArrayList<Operation>(this.operations));
}
return new AccessControlEntry(actor, operations);
}
}
/**
* The set of operations that are allowed on a credential.
*/
public enum Operation {
READ("read"),
WRITE("write");

View File

@@ -19,7 +19,7 @@ package org.springframework.credhub.support;
import java.util.concurrent.TimeUnit;
/**
* Client options for CredHubConnectivity.
* Client options for CredHub connectivity.
*
* @author Mark Paluch
* @author Scott Frederick
@@ -46,7 +46,7 @@ public class ClientOptions {
}
/**
* Create new {@link ClientOptions}.
* Create a {@link ClientOptions} with the provided values.
*
* @param connectionTimeout connection timeout in {@link TimeUnit#MILLISECONDS}, must
* be greater {@literal 0}.
@@ -59,14 +59,18 @@ public class ClientOptions {
}
/**
* @return the connection timeout in {@link TimeUnit#MILLISECONDS}.
* Gets the connection timeout in {@link TimeUnit#MILLISECONDS}.
*
* @return the connection timeout
*/
public int getConnectionTimeout() {
return connectionTimeout;
}
/**
* @return the read timeout in {@link TimeUnit#MILLISECONDS}.
* Gets the read timeout in {@link TimeUnit#MILLISECONDS}
*
* @return the read timeout
*/
public int getReadTimeout() {
return readTimeout;

View File

@@ -1,59 +0,0 @@
/*
*
* * Copyright 2013-2017 the original author or authors.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.springframework.credhub.support;
import com.fasterxml.jackson.annotation.JsonInclude;
public class CredHubRequest {
private CredentialName name;
CredHubRequest(CredentialName name) {
this.name = name;
}
CredHubRequest() {
}
@JsonInclude
public String getName() {
return name.getName();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CredHubRequest)) return false;
CredHubRequest that = (CredHubRequest) o;
return name != null ? name.equals(that.name) : that.name == null;
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
@Override
public String toString() {
return "CredHubRequest{" +
"name=" + name +
'}';
}
}

View File

@@ -1,81 +0,0 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import com.fasterxml.jackson.annotation.JsonProperty;
public class CredHubResponse {
@JsonProperty("errorMessage")
protected final String errorMessage;
CredHubResponse() {
errorMessage = null;
}
CredHubResponse(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getErrorMessage() {
return this.errorMessage;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CredHubResponse that = (CredHubResponse) o;
return errorMessage != null ? errorMessage.equals(that.errorMessage) : that.errorMessage == null;
}
@Override
public int hashCode() {
return errorMessage != null ? errorMessage.hashCode() : 0;
}
@Override
public String toString() {
return "CredHubResponse{" +
"errorMessage='" + errorMessage + '\'' +
'}';
}
public static class CredHubResponseBuilder {
private String errorMessage;
CredHubResponseBuilder() {
}
public CredHubResponse.CredHubResponseBuilder errorMessage(String errorMessage) {
this.errorMessage = errorMessage;
return this;
}
public CredHubResponse build() {
return new CredHubResponse(errorMessage);
}
@Override
public String toString() {
return "CredHubResponseBuilder{" +
"errorMessage='" + errorMessage + '\'' +
'}';
}
}
}

View File

@@ -1,156 +0,0 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import java.util.Map;
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class CredentialData {
private String id;
private CredentialName name;
@JsonProperty("type")
private ValueType valueType;
private Object value;
private String versionCreatedAt;
public CredentialData() {
}
CredentialData(String id, CredentialName name, ValueType valueType, Object value, String versionCreatedAt) {
this.id = id;
this.name = name;
this.valueType = valueType;
this.value = value;
this.versionCreatedAt = versionCreatedAt;
}
public static CredentialDataBuilder builder() {
return new CredentialDataBuilder();
}
public String getId() {
return this.id;
}
public CredentialName getName() {
return this.name;
}
public ValueType getValueType() {
return this.valueType;
}
public Object getValue() {
return this.value;
}
public String getVersionCreatedAt() {
return this.versionCreatedAt;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CredentialData)) return false;
CredentialData that = (CredentialData) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
if (valueType != that.valueType) return false;
if (value != null ? !value.equals(that.value) : that.value != null) return false;
return versionCreatedAt != null ? versionCreatedAt.equals(that.versionCreatedAt) : that.versionCreatedAt == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (valueType != null ? valueType.hashCode() : 0);
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (versionCreatedAt != null ? versionCreatedAt.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CredentialData{" +
"id='" + id + '\'' +
", name=" + name +
", valueType=" + valueType +
", value=" + value +
", versionCreatedAt='" + versionCreatedAt + '\'' +
'}';
}
public static class CredentialDataBuilder {
private String id;
private CredentialName name;
private ValueType valueType;
private Object value;
private String versionCreatedAt;
CredentialDataBuilder() {
}
public CredentialData.CredentialDataBuilder id(String id) {
this.id = id;
return this;
}
public CredentialData.CredentialDataBuilder name(CredentialName name) {
this.name = name;
return this;
}
public CredentialData.CredentialDataBuilder passwordValue(String value) {
this.valueType = ValueType.PASSWORD;
this.value = value;
return this;
}
public CredentialData.CredentialDataBuilder jsonValue(Map<String, Object> value) {
this.valueType = ValueType.JSON;
this.value = value;
return this;
}
public CredentialData.CredentialDataBuilder versionCreatedAt(String versionCreatedAt) {
this.versionCreatedAt = versionCreatedAt;
return this;
}
public CredentialData build() {
return new CredentialData(id, name, valueType, value, versionCreatedAt);
}
@Override
public String toString() {
return "CredentialDataBuilder{" +
"id='" + id + '\'' +
", name=" + name +
", valueType=" + valueType +
", value=" + value +
", versionCreatedAt='" + versionCreatedAt + '\'' +
'}';
}
}
}

View File

@@ -1,138 +0,0 @@
/*
*
* * Copyright 2013-2017 the original author or authors.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.springframework.credhub.support;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
@JsonInclude(NON_EMPTY)
public class CredentialDataResponse extends CredHubResponse {
private List<CredentialData> data;
public CredentialDataResponse() {
}
CredentialDataResponse(String errorMessage) {
super(errorMessage);
}
CredentialDataResponse(List<CredentialData> data) {
super(null);
this.data = data;
}
CredentialDataResponse(String errorMessage, List<CredentialData> data) {
super(errorMessage);
this.data = data;
}
public static CredentialDataResponseBuilder builder() {
return new CredentialDataResponseBuilder();
}
public List<CredentialData> getData() {
return this.data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CredentialDataResponse)) return false;
if (!super.equals(o)) return false;
CredentialDataResponse that = (CredentialDataResponse) o;
return data != null ? data.equals(that.data) : that.data == null;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (data != null ? data.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CredentialDataResponse{" +
"errorMessage=" + errorMessage +
", data=" + data +
'}';
}
public static class CredentialDataResponseBuilder {
private String errorMessage;
private ArrayList<CredentialData> data;
CredentialDataResponseBuilder() {
}
public CredentialDataResponse.CredentialDataResponseBuilder errorMessage(String errorMessage) {
this.errorMessage = errorMessage;
return this;
}
public CredentialDataResponse.CredentialDataResponseBuilder datum(CredentialData datum) {
initData();
this.data.add(datum);
return this;
}
public CredentialDataResponse.CredentialDataResponseBuilder data(Collection<? extends CredentialData> data) {
initData();
this.data.addAll(data);
return this;
}
private void initData() {
if (this.data == null) {
this.data = new ArrayList<CredentialData>();
}
}
public CredentialDataResponse build() {
List<CredentialData> data;
switch (this.data == null ? 0 : this.data.size()) {
case 0:
data = java.util.Collections.emptyList();
break;
case 1:
data = java.util.Collections.singletonList(this.data.get(0));
break;
default:
data = java.util.Collections.unmodifiableList(new ArrayList<CredentialData>(this.data));
}
return new CredentialDataResponse(errorMessage, data);
}
@Override
public String toString() {
return "CredentialDataResponseBuilder{" +
"errorMessage=" + errorMessage + "," +
"data=" + data +
'}';
}
}
}

View File

@@ -0,0 +1,234 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import java.util.Date;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import org.springframework.util.Assert;
/**
* The details of a credential that has been written to CredHub. Clients don't
* typically instantiate objects of this type, but will receive them in response
* to write and retrieve requests. The {@literal id} and {@literal name} fields
* can be used in subsequent requests.
*
* @author Scott Frederick
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class CredentialDetails extends CredentialSummary {
private String id;
@JsonProperty("type")
private ValueType valueType;
private Object value;
/**
* Create a {@link CredentialDetails}.
*/
public CredentialDetails() {
}
/**
* Create a {@link CredentialDetails} from the provided parameters. Intended for
* internal use. Clients will get {@link CredentialDetails} objects populated from
* CredHub responses.
*
* @param id the CredHub-generated unique ID of the credential
* @param name the client-provided name of the credential
* @param valueType the {@link ValueType} of the credential
* @param value the client-provided value for the credential
* @param versionCreatedAt the {@link Date} when this version of the credential was
* created
*/
CredentialDetails(String id, CredentialName name, ValueType valueType,
Object value, Date versionCreatedAt) {
super(name, versionCreatedAt);
this.id = id;
this.valueType = valueType;
this.value = value;
}
/**
* Get the the CredHub-generated unique ID of the credential.
*
* @return the credential ID
*/
public String getId() {
return this.id;
}
/**
* Get the client-provided {@link ValueType} of the credential.
*
* @return the credential type
*/
public ValueType getValueType() {
return this.valueType;
}
/**
* Get the client-provided value for the credential.
*
* @return the credential value
*/
public Object getValue() {
return this.value;
}
/**
* Create a builder for a {@link CredentialDetails} object. Intended for internal
* use in tests. Clients will get {@link CredentialDetails} objects populated from
* CredHub responses.
*
* @return the builder
*/
public static CredentialDetailsBuilder detailsBuilder() {
return new CredentialDetailsBuilder();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof CredentialDetails))
return false;
CredentialDetails that = (CredentialDetails) o;
if (id != null ? !id.equals(that.id) : that.id != null)
return false;
if (valueType != that.valueType)
return false;
if (value != null ? !value.equals(that.value) : that.value != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (valueType != null ? valueType.hashCode() : 0);
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result
+ (versionCreatedAt != null ? versionCreatedAt.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CredentialDetails{"
+ "id='" + id + '\''
+ ", name=" + name
+ ", valueType=" + valueType
+ ", value=" + value
+ ", versionCreatedAt='" + versionCreatedAt + '\'' +
'}';
}
/**
* A builder that provides a fluent API for constructing {@link CredentialDetails}
* instances. Intended to be used internally for testing.
*/
public static class CredentialDetailsBuilder {
private String id;
private CredentialName name;
private ValueType valueType;
private Object value;
private Date versionCreatedAt;
CredentialDetailsBuilder() {
}
/**
* Set the ID of the credential.
*
* @param id the ID; must not be {@literal null}
* @return the builder
*/
public CredentialDetailsBuilder id(String id) {
Assert.notNull(id, "id must not be null");
this.id = id;
return this;
}
/**
* Set the name of the credential.
*
* @param name the name; must not be {@literal null}
* @return the builder
*/
public CredentialDetailsBuilder name(CredentialName name) {
Assert.notNull(name, "name must not be null");
this.name = name;
return this;
}
/**
* Set a password value and {@link ValueType#PASSWORD} type for the credential.
*
* @param value the password value; must not be {@literal null}
* @return the builder
*/
public CredentialDetailsBuilder passwordValue(String value) {
Assert.notNull(value, "value must not be null");
this.valueType = ValueType.PASSWORD;
this.value = value;
return this;
}
/**
* Set a JSON value and {@link ValueType#JSON} type for the credential.
*
* @param value the JSON value; must not be {@literal null}
* @return the builder
*/
public CredentialDetailsBuilder jsonValue(Map<String, Object> value) {
Assert.notNull(value, "value must not be null");
this.valueType = ValueType.JSON;
this.value = value;
return this;
}
/**
* Set a creation date for the credential.
*
* @param versionCreatedAt the creation date; must not be {@literal null}
* @return the builder
*/
public CredentialDetailsBuilder versionCreatedAt(Date versionCreatedAt) {
Assert.notNull(versionCreatedAt, "versionCreatedAt must not be null");
this.versionCreatedAt = versionCreatedAt;
return this;
}
/**
* Construct a {@link CredentialDetails} from the provided values.
*
* @return a {@link CredentialDetails}
*/
public CredentialDetails build() {
return new CredentialDetails(id, name, valueType, value, versionCreatedAt);
}
}
}

View File

@@ -0,0 +1,177 @@
/*
*
* * Copyright 2013-2017 the original author or authors.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.springframework.credhub.support;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.util.Assert;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
/**
* A collection of {@link CredentialDetails}. Clients don't typically instantiate
* objects of this type, but will receive them in response to write and retrieve
* requests.
*
* @author Scott Frederick
*/
@JsonInclude(NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown = true)
public class CredentialDetailsData {
private List<CredentialDetails> data;
/**
* Create a {@link CredentialDetailsData}.
*/
public CredentialDetailsData() {
}
/**
* Create a {@link CredentialDetailsData} from the provided parameters. Intended for internal
* use. Clients will get {@link CredentialDetailsData} objects populated from
* CredHub responses.
*
* @param data a collection of {@link CredentialDetails}
*/
CredentialDetailsData(List<CredentialDetails> data) {
this.data = data;
}
/**
* Get the collection of {@link CredentialDetails}.
*
* @return the collection of {@link CredentialDetails}
*/
public List<CredentialDetails> getData() {
return this.data;
}
/**
* Create a builder for a {@link CredentialDetailsData} object. Intended for internal
* use. Clients will get {@link CredentialDetailsData} objects populated from
* CredHub responses.
*
* @return the builder
*/
public static CredentialDetailsDataBuilder builder() {
return new CredentialDetailsDataBuilder();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof CredentialDetailsData))
return false;
if (!super.equals(o))
return false;
CredentialDetailsData that = (CredentialDetailsData) o;
return data != null ? data.equals(that.data) : that.data == null;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (data != null ? data.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CredentialDetailResponse{"
+ "data=" + data
+ '}';
}
/**
* A builder that provides a fluent API for constructing {@link CredentialDetailsData}
* instances. Intended to be used internally for testing.
*/
public static class CredentialDetailsDataBuilder {
private List<CredentialDetails> data;
/**
* Create a {@link CredentialDetailsDataBuilder}.
*/
CredentialDetailsDataBuilder() {
}
/**
* Add a {@link CredentialDetails} to the collection of details.
*
* @param datum a {@link CredentialDetails} to add; must not be
* {@literal null}
* @return the builder
*/
public CredentialDetailsDataBuilder datum(CredentialDetails datum) {
Assert.notNull(datum, "datum must not be null");
initData();
this.data.add(datum);
return this;
}
/**
* Add a collection of {@link CredentialDetails} to the collection of details.
*
* @param data a collection of {@link CredentialDetails} to add;
* must not be {@literal null}
* @return the builder
*/
public CredentialDetailsDataBuilder data(Collection<? extends CredentialDetails> data) {
Assert.notNull(data, "data must not be null");
initData();
this.data.addAll(data);
return this;
}
private void initData() {
if (this.data == null) {
this.data = new ArrayList<CredentialDetails>();
}
}
/**
* Construct a {@link CredentialDetailsData} from the provided values.
*
* @return a {@link CredentialDetailsData}
*/
public CredentialDetailsData build() {
List<CredentialDetails> data;
switch (this.data == null ? 0 : this.data.size()) {
case 0:
data = java.util.Collections.emptyList();
break;
case 1:
data = java.util.Collections.singletonList(this.data.get(0));
break;
default:
data = java.util.Collections
.unmodifiableList(new ArrayList<CredentialDetails>(this.data));
}
return new CredentialDetailsData(data);
}
}
}

View File

@@ -16,30 +16,75 @@
package org.springframework.credhub.support;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import org.springframework.util.StringUtils;
import java.util.Arrays;
@Data
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* The client-provided name of a credential stored in CredHub. Credential names are
* constructed of segments separated by the "/" character, like Unix paths.
*
* @author Scott Frederick
*/
public class CredentialName {
@JsonIgnore
private final String[] segments;
protected final String[] segments;
/**
* Create a name from the provided value. The name must consist of segments
* separated by the "/" character.
*
* @param name the credential name; must not be {@literal null}
*/
CredentialName(String name) {
Assert.notNull("name", "name must not be null");
String[] split = name.split("/");
Assert.isTrue(split.length > 2, "name must include at least one segment separated by '/'");
// remove the "/c/" prefix
this.segments = Arrays.copyOfRange(split, 2, split.length);
}
/**
* Create a name from the provided segments.
*
* @param segments the list of name segments; must not be {@literal null}
*/
CredentialName(String... segments) {
Assert.notNull(segments, "segments must not be null");
this.segments = segments;
}
/**
* Builds a name from the provided segments.
*
* @return the credential name
*/
@JsonInclude
public String getName() {
return "/c/" + StringUtils.arrayToDelimitedString(segments, "/");
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof CredentialName))
return false;
CredentialName that = (CredentialName) o;
return Arrays.equals(segments, that.segments);
}
@Override
public int hashCode() {
return Arrays.hashCode(segments);
}
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import org.springframework.util.Assert;
/**
* A summary of a credential that has been written to CredHub. Clients don't typically
* instantiate objects of this type, but will receive them in response to write and
* retrieve requests. The {@literal name} field can be used in subsequent requests.
*
* @author Scott Frederick
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class CredentialSummary {
protected CredentialName name;
protected Date versionCreatedAt;
/**
* Create a {@link CredentialSummary}. Intended for internal use.
*/
CredentialSummary() {
}
/**
* Create a {@link CredentialSummary} from the provided parameters. Intended for
* internal use. Clients will get {@link CredentialSummary} objects populated from
* CredHub responses.
*
* @param name the name of the credential
* @param versionCreatedAt the {@link Date} when this version of the credential was
* created
*/
CredentialSummary(CredentialName name, Date versionCreatedAt) {
this.name = name;
this.versionCreatedAt = versionCreatedAt;
}
/**
* Get the client-provided name of the credential.
*
* @return the credential name
*/
public CredentialName getName() {
return this.name;
}
/**
* Get the CredHub-generated {@link Date} when this version of the credential was created.
*
* @return the credential version creation {@link Date}
*/
public Date getVersionCreatedAt() {
return this.versionCreatedAt;
}
/**
* Create a builder for a {@link CredentialSummary} object. Intended for internal
* use in tests. Clients will get {@link CredentialSummary} objects populated from
* CredHub responses.
*
* @return the builder
*/
public static CredentialSummaryBuilder summaryBuilder() {
return new CredentialSummaryBuilder();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof CredentialSummary))
return false;
CredentialSummary that = (CredentialSummary) o;
if (name != null ? !name.equals(that.name) : that.name != null)
return false;
return versionCreatedAt != null ? versionCreatedAt.equals(that.versionCreatedAt)
: that.versionCreatedAt == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result
+ (versionCreatedAt != null ? versionCreatedAt.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CredentialSummary{"
+ "name=" + name
+ ", versionCreatedAt='" + versionCreatedAt + '\''
+ '}';
}
/**
* A builder that provides a fluent API for constructing {@link CredentialSummary}
* instances. Intended to be used internally for testing.
*/
public static class CredentialSummaryBuilder {
protected CredentialName name;
protected Date versionCreatedAt;
CredentialSummaryBuilder() {
}
/**
* Set the name of the credential.
*
* @param name the name; must not be {@literal null}
* @return the builder
*/
public CredentialSummaryBuilder name(CredentialName name) {
Assert.notNull(name, "name must not be null");
this.name = name;
return this;
}
/**
* Set a creation date for the credential.
*
* @param versionCreatedAt the creation date; must not be {@literal null}
* @return the builder
*/
public CredentialSummaryBuilder versionCreatedAt(Date versionCreatedAt) {
Assert.notNull(versionCreatedAt, "versionCreatedAt must not be null");
this.versionCreatedAt = versionCreatedAt;
return this;
}
/**
* Construct a {@link CredentialSummary} from the provided values.
*
* @return a {@link CredentialSummary}
*/
public CredentialSummary build() {
return new CredentialSummary(name, versionCreatedAt);
}
}
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import org.springframework.util.Assert;
/**
* A collection of {@link CredentialSummary}s. Clients don't typically instantiate
* objects of this type, but will receive them in response to write and retrieve
* requests.
*
* @author Scott Frederick
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class CredentialSummaryData {
private List<CredentialSummary> credentials;
/**
* Create a {@link CredentialSummaryData}.
*/
CredentialSummaryData() {
}
/**
* Create a {@link CredentialSummaryData} from the provided parameters. Intended for internal
* use. Clients will get {@link CredentialSummaryData} objects populated from
* CredHub responses.
*
* @param credentials a collection of {@link CredentialSummary}s
*/
CredentialSummaryData(List<CredentialSummary> credentials) {
this.credentials = credentials;
}
/**
* Get the collection of {@link CredentialSummary}s.
*
* @return the collection of {@link CredentialSummary}s
*/
public List<CredentialSummary> getCredentials() {
return this.credentials;
}
/**
* Create a builder for a {@link CredentialSummaryData} object. Intended for internal
* use. Clients will get {@link CredentialSummaryData} objects populated from
* CredHub responses.
*
* @return the builder
*/
public static CredentialSummaryDataBuilder builder() {
return new CredentialSummaryDataBuilder();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof CredentialSummaryData))
return false;
if (!super.equals(o))
return false;
CredentialSummaryData that = (CredentialSummaryData) o;
return credentials != null ? credentials.equals(that.credentials)
: that.credentials == null;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (credentials != null ? credentials.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CredentialSummaryResponse{"
+ "credentials=" + credentials
+ '}';
}
/**
* Create a builder for a {@link CredentialSummaryData} object. Intended for internal
* use. Clients will get {@link CredentialSummaryData} objects populated from
* CredHub responses.
*
* @return the builder
*/
public static class CredentialSummaryDataBuilder {
private List<CredentialSummary> credentialSummaries;
CredentialSummaryDataBuilder() {
}
/**
* Add a {@link CredentialSummary} to the collection of summaries.
*
* @param credential the {@link CredentialSummary} to add; must not be
* {@literal null}
* @return the builder
*/
public CredentialSummaryDataBuilder credential(CredentialSummary credential) {
Assert.notNull(credential, "credential must not be null");
initCredentials();
this.credentialSummaries.add(credential);
return this;
}
/**
* Add a collection of {@link CredentialSummary}s to the collection of summaries.
*
* @param credentials the {@link CredentialSummary}s to add; must not be
* {@literal null}
* @return the builder
*/
public CredentialSummaryDataBuilder credentials(
Collection<? extends CredentialSummary> credentials) {
Assert.notNull(credentials, "credentials must not be null");
initCredentials();
this.credentialSummaries.addAll(credentials);
return this;
}
private void initCredentials() {
if (this.credentialSummaries == null) {
this.credentialSummaries = new ArrayList<CredentialSummary>();
}
}
/**
* Construct a {@link CredentialSummaryData} from the provided values.
*
* @return a {@link CredentialSummaryData}
*/
public CredentialSummaryData build() {
List<CredentialSummary> credentialSummaries;
switch (this.credentialSummaries == null ? 0
: this.credentialSummaries.size()) {
case 0:
credentialSummaries = java.util.Collections.emptyList();
break;
case 1:
credentialSummaries = java.util.Collections
.singletonList(this.credentialSummaries.get(0));
break;
default:
credentialSummaries = java.util.Collections.unmodifiableList(
new ArrayList<CredentialSummary>(this.credentialSummaries));
}
return new CredentialSummaryData(credentialSummaries);
}
}
}

View File

@@ -1,204 +0,0 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class FindResponse extends CredHubResponse {
private List<FoundCredential> foundCredentials;
FindResponse(List<FoundCredential> foundCredentials) {
this.foundCredentials = foundCredentials;
}
public FindResponse(String errorMessage, List<FoundCredential> foundCredentials) {
super(errorMessage);
this.foundCredentials = foundCredentials;
}
public static FindResponseBuilder builder() {
return new FindResponseBuilder();
}
public List<FoundCredential> getFoundCredentials() {
return this.foundCredentials;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FindResponse)) return false;
if (!super.equals(o)) return false;
FindResponse that = (FindResponse) o;
return foundCredentials != null ? foundCredentials.equals(that.foundCredentials) : that.foundCredentials == null;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (foundCredentials != null ? foundCredentials.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "FindResponse{" +
"errorMessage='" + errorMessage + '\'' +
", foundCredentials=" + foundCredentials +
'}';
}
public static class FindResponseBuilder {
private String errorMessage;
private ArrayList<FoundCredential> foundCredentials;
FindResponseBuilder() {
}
public FindResponse.FindResponseBuilder foundCredential(FoundCredential foundCredential) {
initFoundCredentials();
this.foundCredentials.add(foundCredential);
return this;
}
public FindResponse.FindResponseBuilder foundCredentials(Collection<? extends FoundCredential> foundCredentials) {
initFoundCredentials();
this.foundCredentials.addAll(foundCredentials);
return this;
}
private void initFoundCredentials() {
if (this.foundCredentials == null) {
this.foundCredentials = new ArrayList<FoundCredential>();
}
}
public FindResponse build() {
List<FoundCredential> foundCredentials;
switch (this.foundCredentials == null ? 0 : this.foundCredentials.size()) {
case 0:
foundCredentials = java.util.Collections.emptyList();
break;
case 1:
foundCredentials = java.util.Collections.singletonList(this.foundCredentials.get(0));
break;
default:
foundCredentials = java.util.Collections.unmodifiableList(new ArrayList<FoundCredential>(this.foundCredentials));
}
return new FindResponse(errorMessage, foundCredentials);
}
@Override
public String toString() {
return "FindResponseBuilder{" +
"foundCredentials=" + foundCredentials +
'}';
}
public FindResponseBuilder errorMessage(String errorMessage) {
this.errorMessage = errorMessage;
return this;
}
}
public static class FoundCredential {
private CredentialName name;
private String versionCreatedAt;
FoundCredential(CredentialName name, String versionCreatedAt) {
this.name = name;
this.versionCreatedAt = versionCreatedAt;
}
public static FoundCredentialBuilder builder() {
return new FoundCredentialBuilder();
}
public CredentialName getName() {
return this.name;
}
public String getVersionCreatedAt() {
return this.versionCreatedAt;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FoundCredential)) return false;
FoundCredential that = (FoundCredential) o;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
return versionCreatedAt != null ? versionCreatedAt.equals(that.versionCreatedAt) : that.versionCreatedAt == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (versionCreatedAt != null ? versionCreatedAt.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "FoundCredential{" +
"name=" + name +
", versionCreatedAt='" + versionCreatedAt + '\'' +
'}';
}
public static class FoundCredentialBuilder {
private CredentialName name;
private String versionCreatedAt;
FoundCredentialBuilder() {
}
public FoundCredential.FoundCredentialBuilder name(CredentialName name) {
this.name = name;
return this;
}
public FoundCredential.FoundCredentialBuilder versionCreatedAt(String versionCreatedAt) {
this.versionCreatedAt = versionCreatedAt;
return this;
}
public FoundCredential build() {
return new FoundCredential(name, versionCreatedAt);
}
@Override
public String toString() {
return "FoundCredentialBuilder{" +
"name=" + name +
", versionCreatedAt='" + versionCreatedAt + '\'' +
'}';
}
}
}
}

View File

@@ -1,32 +0,0 @@
/*
*
* * Copyright 2013-2017 the original author or authors.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.springframework.credhub.support;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class ReadRequest extends CredHubRequest {
@Builder
public ReadRequest(CredentialName name) {
super(name);
}
}

View File

@@ -16,18 +16,132 @@
package org.springframework.credhub.support;
import lombok.Builder;
import lombok.Data;
import org.springframework.util.Assert;
@Data
import java.util.Arrays;
/**
* The client-provided name of a credential that stores service instance binding
* credentials. Service instance binding credential names consist of four segments:
* service broker name, service offering name, service binding GUID, and credential
* name. When these values are combined the full name of the credential will be of
* the form
* {@literal /c/service-broker-name/service-offering-name/binding-GUID/credential-name}.
*
* Objects of this type are created by clients and included as part of requests.
*
* @author Scott Frederick
*/
public class ServiceInstanceCredentialName extends CredentialName {
@Builder
public ServiceInstanceCredentialName(String serviceBrokerName, String serviceOfferingName, String serviceBindingId, String credentialName) {
/**
* Create a {@link ServiceInstanceCredentialName} from the required name fields.
* Intended for internal use in tests. Clients should use
* {@link #builder()} to construct instances of this class.
*
* @param serviceBrokerName the human-readable name of the service broker
* @param serviceOfferingName the human-readable name of the service offering
* @param serviceBindingId the GUID of the service binding
* @param credentialName the name of the binding credential
*/
ServiceInstanceCredentialName(String serviceBrokerName, String serviceOfferingName,
String serviceBindingId, String credentialName) {
super(serviceBrokerName, serviceOfferingName, serviceBindingId, credentialName);
}
/**
* Create a builder that provides a fluent API for providing the values required
* to construct a {@link ServiceInstanceCredentialName}.
*
* @return the builder
*/
public static ServiceInstanceCredentialNameBuilder builder() {
return new ServiceInstanceCredentialNameBuilder();
}
@Override
public String getName() {
return null;
public String toString() {
return "ServiceInstanceCredentialName{"
+ "segments=" + Arrays.toString(segments)
+ "}";
}
/**
* A builder that provides a fluent API for constructing
* {@link ServiceInstanceCredentialName} instances.
*/
public static class ServiceInstanceCredentialNameBuilder {
private String serviceBrokerName;
private String serviceOfferingName;
private String serviceBindingId;
private String credentialName;
/**
* Create a {@link ServiceInstanceCredentialNameBuilder}
*/
ServiceInstanceCredentialNameBuilder() {
}
/**
* Set the service broker name segment of the credential name. This is typically
* a human-readable name and should be unique among all service brokers in
* Cloud Foundry.
*
* @param serviceBrokerName the service broker name; must not be {@literal null}
* @return the builder
*/
public ServiceInstanceCredentialNameBuilder serviceBrokerName(String serviceBrokerName) {
Assert.notNull(serviceBrokerName, "serviceBrokerName must not be null");
this.serviceBrokerName = serviceBrokerName;
return this;
}
/**
* Set the service offering name segment of the credential name. This is typically
* a human-readable name and should be unique within the service broker.
*
* @param serviceOfferingName the service offering name; must not be {@literal null}
* @return the builder
*/
public ServiceInstanceCredentialNameBuilder serviceOfferingName(String serviceOfferingName) {
Assert.notNull(serviceOfferingName, "serviceOfferingName must not be null");
this.serviceOfferingName = serviceOfferingName;
return this;
}
/**
* Set the service binding ID segment of the credential name. This value is
* generated by Cloud Foundry when a service instance is bound to an application
* and is in the form of a GUID.
*
* @param serviceBindingId the service binding ID; must not be {@literal null}
* @return the builder
*/
public ServiceInstanceCredentialNameBuilder serviceBindingId(String serviceBindingId) {
Assert.notNull(serviceBindingId, "serviceBindingId must not be null");
this.serviceBindingId = serviceBindingId;
return this;
}
/**
* Set the credential name segment of the full credential name.
*
* @param credentialName the credential name; must not be {@literal null}
* @return the builder
*/
public ServiceInstanceCredentialNameBuilder credentialName(String credentialName) {
Assert.notNull(credentialName, "credentialName must not be null");
this.credentialName = credentialName;
return this;
}
/**
* Create a {@link ServiceInstanceCredentialName} from the provided values.
*
* @return a {@link ServiceInstanceCredentialName}
*/
public ServiceInstanceCredentialName build() {
return new ServiceInstanceCredentialName(serviceBrokerName,
serviceOfferingName, serviceBindingId, credentialName);
}
}
}

View File

@@ -16,22 +16,37 @@
package org.springframework.credhub.support;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.util.Assert;
@Data
@EqualsAndHashCode(callSuper = true)
import java.util.Arrays;
/**
* The client-provided name of a credential. The name consists of one or more segments.
* When the value of each segment are combined the full name of the credential will be of
* the form
* {@literal /c/segment1/segment2/segment3}.
*
* Objects of this type are created by clients and included as part of requests.
*
* @author Scott Frederick
*/
public class SimpleCredentialName extends CredentialName {
@Builder
/**
* Create a {@link SimpleCredentialName} from the provided segments.
*
* @param segments the credential name segments; must not be {@literal null} and must
* contain at least one segment
*/
public SimpleCredentialName(String... segments) {
super(segments);
Assert.notNull(segments, "segments must not be null");
Assert.isTrue(segments.length > 0, "at least one segment must be provided");
}
public static class SimpleCredentialNameBuilder {
public SimpleCredentialNameBuilder segments(String... segments) {
this.segments = segments;
return this;
}
@Override
public String toString() {
return "SimpleCredentialName{"
+ "segments=" + Arrays.toString(segments)
+ "}";
}
}

View File

@@ -16,17 +16,20 @@
package org.springframework.credhub.support;
import java.io.FileReader;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import java.io.FileReader;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
/**
* Client configuration for SSL connectivity.
*/
public class SslConfiguration {
private static final char[] KEY_PASSWORD = "keystore".toCharArray();
private static final String CERTIFICATE_NAME = "credhub-cert";
@@ -35,17 +38,39 @@ public class SslConfiguration {
private KeyStore trustStore;
private KeyStore keyStore;
/**
* Create an empty {@link SslConfiguration}. Intended for internal use.
*/
public SslConfiguration() {
}
public static SslConfiguration forContainerCert(String instanceCertLocation, String instanceKeyLocation) {
/**
* Create an {@link SslConfiguration} that uses a certificate and private key that
* have been placed in a Cloud Foundry application container for use with mutual SSL
* authentication to CredHub.
*
* @param instanceCertLocation the absolute path of the certificate file in the app
* instance container
* @param instanceKeyLocation the absolute path of the private key file in the app
* instance container
* @return the {@link SslConfiguration} configured to use the container certificate
* and private key
*/
public static SslConfiguration forContainerCert(String instanceCertLocation,
String instanceKeyLocation) {
SslConfiguration sslConfiguration = new SslConfiguration();
KeyStore keyStore = sslConfiguration.buildKeyStore(instanceCertLocation, instanceKeyLocation);
KeyStore keyStore = sslConfiguration.buildKeyStore(instanceCertLocation,
instanceKeyLocation);
sslConfiguration.setKeyStore(keyStore);
sslConfiguration.setTrustStore(keyStore);
return sslConfiguration;
}
/**
* Get the {@link KeyStore key store} resource used to configure the SSL context.
*
* @return the key store
*/
public KeyStore getKeyStore() {
return keyStore;
}
@@ -54,6 +79,11 @@ public class SslConfiguration {
this.keyStore = keyStore;
}
/**
* Get the {@link KeyStore trust store} resource used to configure the SSL context.
*
* @return the trust store
*/
public KeyStore getTrustStore() {
return trustStore;
}
@@ -62,46 +92,91 @@ public class SslConfiguration {
this.trustStore = keyStore;
}
/**
* Get the password used to secure the generated key store.
*
* @return they key store password
*/
public char[] getKeyPassword() {
return KEY_PASSWORD;
}
private KeyStore buildKeyStore(String instanceCertLocation, String instanceKeyLocation) {
/**
* Build a {@link KeyStore} using the container certificate and private key.
*
* @param instanceCertLocation the absolute path of the certificate file in the app
* instance container
* @param instanceKeyLocation the absolute path of the private key file in the app
* instance container
* @return the created key store
*/
private KeyStore buildKeyStore(String instanceCertLocation,
String instanceKeyLocation) {
Certificate cert = parseCertificate(instanceCertLocation);
PrivateKey key = parsePrivateKey(instanceKeyLocation);
return createKeyStore(cert, key);
}
/**
* Parse a PEM-formatted certificate and convert to a {@link Certificate}.
*
* @param certificateLocation the absolute path of the certificate file in the app
* instance container
* @return the created {@link Certificate}
*/
private Certificate parseCertificate(String certificateLocation) {
try {
PEMParser parser = new PEMParser(new FileReader(certificateLocation));
X509CertificateHolder certHolder = (X509CertificateHolder) parser.readObject();
X509CertificateHolder certHolder =
(X509CertificateHolder) parser.readObject();
JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
return converter.getCertificate(certHolder);
} catch (Exception e) {
throw new IllegalArgumentException("Error parsing and loading certificate from location " + certificateLocation, e);
}
catch (Exception e) {
throw new IllegalArgumentException(
"Error parsing and loading certificate from location "
+ certificateLocation,
e);
}
}
/**
* Parse a PEM-formatted key and convert to a {@link PrivateKey}.
*
* @param keyLocation the absolute path of the key file in the app
* instance container
* @return the created {@link PrivateKey}
*/
private PrivateKey parsePrivateKey(String keyLocation) {
try {
PEMParser reader = new PEMParser(new FileReader(keyLocation));
PEMKeyPair key = (PEMKeyPair) reader.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
return converter.getKeyPair(key).getPrivate();
} catch (Exception e) {
throw new IllegalArgumentException("Error parsing and loading private key from location " + keyLocation, e);
}
catch (Exception e) {
throw new IllegalArgumentException(
"Error parsing and loading private key from location " + keyLocation,
e);
}
}
/**
* Create a {@link KeyStore} from the provided certificate and private key.
*
* @param cert the certifcate to add to the key store
* @param key the private key to add to the key store
* @return the created {@link KeyStore}
*/
private KeyStore createKeyStore(Certificate cert, PrivateKey key) {
try {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null);
keystore.setCertificateEntry(CERTIFICATE_NAME, cert);
keystore.setKeyEntry(KEY_NAME, key, KEY_PASSWORD, new Certificate[]{cert});
keystore.setKeyEntry(KEY_NAME, key, KEY_PASSWORD, new Certificate[] { cert });
return keystore;
} catch (Exception e) {
}
catch (Exception e) {
throw new IllegalArgumentException("Error creating keystore ", e);
}
}

View File

@@ -20,8 +20,20 @@ package org.springframework.credhub.support;
import com.fasterxml.jackson.annotation.JsonCreator;
/**
* The types of credentials that can be written to CredHub.
*/
public enum ValueType {
/**
* A password credential consists of a single string value. The password value
* is provided by the client (i.e. not generated by CredHub).
*/
PASSWORD("password"),
/**
* A JSON credential consists of one or more fields in a JSON document. The keys and
* values in the JSON document are determined by the client.
*/
JSON("json");
private final String type;
@@ -30,10 +42,21 @@ public enum ValueType {
this.type = type;
}
/**
* Get the type value that will be used in requests to CredHub.
*
* @return the type value
*/
public String type() {
return type;
}
/**
* Convert a {@literal String} type to its enum value.
*
* @param type the {@literal String} type to convert
* @return the enum value
*/
@JsonCreator
public static ValueType getTypeByString(String type) {
for (ValueType e : ValueType.values()) {

View File

@@ -18,94 +18,157 @@
package org.springframework.credhub.support;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Singular;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import org.springframework.util.Assert;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
import static org.springframework.credhub.support.ValueType.JSON;
/**
* The details of a request to write a new or update an existing credential in CredHub.
*
* @author Scott Frederick
*/
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class WriteRequest extends CredHubRequest {
public class WriteRequest {
private boolean overwrite;
private CredentialName name;
private ValueType valueType;
private Object value;
@JsonInclude(NON_EMPTY)
private List<AccessControlEntry> accessControlEntries;
private WriteRequest(CredentialName name, boolean overwrite, Object value, ValueType valueType,
@Singular List<AccessControlEntry> accessControlEntries) {
super(name);
/**
* Create a {@link WriteRequest} from the provided parameters. Intended for internal
* use. Clients should use {@link #builder()} to construct instances of this class.
*
* @param name the name of the credential
* @param overwrite {@literal false} to create a new credential, or
* {@literal true} to update and existing credential
* @param value the value of the credential
* @param valueType the {@link ValueType} of the credential
* @param accessControlEntries requirements for access control for the credential
*/
private WriteRequest(CredentialName name, boolean overwrite,
Object value, ValueType valueType,
List<AccessControlEntry> accessControlEntries) {
this.name = name;
this.overwrite = overwrite;
this.valueType = valueType;
this.value = value;
this.accessControlEntries = accessControlEntries;
}
/**
* Get the value of the {@literal boolean} flag indicating whether the CredHub
* should create a new credential or update an existing credential.
*
* @return the {@literal boolean} overwrite value
*/
public boolean isOverwrite() {
return this.overwrite;
}
/**
* Get the {@link CredentialName} of the credential.
*
* @return the name of the credential
*/
@JsonInclude
public String getName() {
return name.getName();
}
/**
* Get the value of the credential.
*
* @return the value of the credential
*/
public Object getValue() {
return this.value;
}
/**
* Get the {@link ValueType} of the credential.
*
* @return the type of the credential
*/
public String getType() {
return valueType.type();
}
/**
* Get the set of {@link AccessControlEntry} to assign to the credential.
*
* @return the set of {@link AccessControlEntry}
*/
public List<AccessControlEntry> getAccessControlEntries() {
return this.accessControlEntries;
}
/**
* Create a builder that provides a fluent API for providing the values required
* to construct a {@link WriteRequest}.
*
* @return a builder
*/
public static WriteRequestBuilder builder() {
return new WriteRequestBuilder();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof WriteRequest)) return false;
if (!super.equals(o)) return false;
if (this == o)
return true;
if (!(o instanceof WriteRequest))
return false;
WriteRequest that = (WriteRequest) o;
if (overwrite != that.overwrite) return false;
if (valueType != that.valueType) return false;
if (value != null ? !value.equals(that.value) : that.value != null) return false;
return accessControlEntries != null ? accessControlEntries.equals(that.accessControlEntries) : that.accessControlEntries == null;
if (overwrite != that.overwrite)
return false;
if (!name.equals(that.name))
return false;
if (valueType != that.valueType)
return false;
if (!value.equals(that.value))
return false;
return accessControlEntries.equals(that.accessControlEntries);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (overwrite ? 1 : 0);
result = 31 * result + (valueType != null ? valueType.hashCode() : 0);
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (accessControlEntries != null ? accessControlEntries.hashCode() : 0);
int result = (overwrite ? 1 : 0);
result = 31 * result + name.hashCode();
result = 31 * result + valueType.hashCode();
result = 31 * result + value.hashCode();
result = 31 * result + accessControlEntries.hashCode();
return result;
}
@Override
public String toString() {
return "WriteRequest{" +
"overwrite=" + overwrite +
", valueType=" + valueType +
", value=" + value +
", accessControlEntries=" + accessControlEntries +
'}';
}
public boolean isOverwrite() {
return this.overwrite;
}
public Object getValue() {
return this.value;
}
public String getType() {
return valueType.type();
}
public List<AccessControlEntry> getAccessControlEntries() {
return this.accessControlEntries;
return "WriteRequest{"
+ "overwrite=" + overwrite
+ ", name=" + name
+ ", valueType=" + valueType
+ ", value=" + value
+ ", accessControlEntries=" + accessControlEntries
+ '}';
}
/**
* A builder that provides a fluent API for constructing {@link WriteRequest}s.
*/
public static class WriteRequestBuilder {
private CredentialName name;
private boolean overwrite;
@@ -113,70 +176,124 @@ public class WriteRequest extends CredHubRequest {
private ValueType valueType;
private ArrayList<AccessControlEntry> accessControlEntries;
/**
* Create a {@link WriteRequestBuilder}. Intended for internal use.
*/
WriteRequestBuilder() {
}
/**
* Set the value of a password credential. A password credential consists of
* a single string value. The type of the credential is set to {@link ValueType#PASSWORD}.
*
* @param value the password credential value; must not be {@literal null}
* @return the builder
*/
public WriteRequestBuilder passwordValue(String value) {
Assert.notNull(value, "value must not be null");
this.valueType = ValueType.PASSWORD;
this.value = value;
return this;
}
/**
* Set the value of a JSON credential. A JSON credential consists of
* one or more fields in a JSON document. The provided {@literal Map} parameter.
* will be converted to a JSON document before sending to CredHub. The type of
* the credential is set to {@link ValueType#JSON}.
*
* @param value the json credential value; must not be {@literal null}
* @return the builder
*/
public WriteRequestBuilder jsonValue(Map<String, Object> value) {
Assert.notNull(value, "value must not be null");
this.valueType = JSON;
this.value = value;
return this;
}
/**
* Set the {@link CredentialName} for the credential.
*
* @param name the credential name; must not be {@literal null}
* @return the builder
*/
public WriteRequestBuilder name(CredentialName name) {
Assert.notNull(name, "name must not be null");
this.name = name;
return this;
}
/**
* Sets a {@literal boolean} value indicating whether CredHub should create a new
* credential or update and existing credential.
*
* @param overwrite {@literal false} to create a new credential, or
* {@literal true} to update and existing credential
* @return the builder
*/
public WriteRequestBuilder overwrite(boolean overwrite) {
this.overwrite = overwrite;
return this;
}
/**
* Add an {@link AccessControlEntry} to the controls that will be assigned to the
* credential.
*
* @param accessControlEntry an {@link AccessControlEntry} to assign to the
* credential
* @return the builder
*/
public WriteRequestBuilder accessControlEntry(AccessControlEntry accessControlEntry) {
if (this.accessControlEntries == null)
this.accessControlEntries = new ArrayList<AccessControlEntry>();
initAccessControls();
this.accessControlEntries.add(accessControlEntry);
return this;
}
/**
* Add a collection of {@link AccessControlEntry}s to the controls that will be
* assigned to the credential.
*
* @param accessControlEntries an collection of {@link AccessControlEntry}s to
* assign to the credential
* @return the builder
*/
public WriteRequestBuilder accessControlEntries(Collection<? extends AccessControlEntry> accessControlEntries) {
if (this.accessControlEntries == null)
this.accessControlEntries = new ArrayList<AccessControlEntry>();
initAccessControls();
this.accessControlEntries.addAll(accessControlEntries);
return this;
}
public WriteRequest build() {
List<AccessControlEntry> accessControlEntries;
switch (this.accessControlEntries == null ? 0 : this.accessControlEntries.size()) {
case 0:
accessControlEntries = java.util.Collections.emptyList();
break;
case 1:
accessControlEntries = java.util.Collections.singletonList(this.accessControlEntries.get(0));
break;
default:
accessControlEntries = java.util.Collections.unmodifiableList(new ArrayList<AccessControlEntry>(this.accessControlEntries));
private void initAccessControls() {
if (this.accessControlEntries == null) {
this.accessControlEntries = new ArrayList<AccessControlEntry>();
}
return new WriteRequest(name, overwrite, value, valueType, accessControlEntries);
}
@Override
public String toString() {
return "WriteRequestBuilder{" +
"name=" + name +
", overwrite=" + overwrite +
", value=" + value +
", valueType=" + valueType +
", accessControlEntries=" + accessControlEntries +
'}';
/**
* Create a {@link WriteRequest} from the provided values.
*
* @return a {@link WriteRequest}
*/
public WriteRequest build() {
List<AccessControlEntry> accessControlEntries;
switch (this.accessControlEntries == null ? 0
: this.accessControlEntries.size()) {
case 0:
accessControlEntries = java.util.Collections.emptyList();
break;
case 1:
accessControlEntries = java.util.Collections
.singletonList(this.accessControlEntries.get(0));
break;
default:
accessControlEntries = java.util.Collections.unmodifiableList(
new ArrayList<AccessControlEntry>(this.accessControlEntries));
}
return new WriteRequest(name, overwrite, value, valueType,
accessControlEntries);
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.credhub.configuration;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.junit.Test;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.credhub.support.ClientOptions;
import org.springframework.credhub.support.SslConfiguration;
@@ -33,12 +34,14 @@ public class ClientHttpRequestFactoryFactoryTests {
@Test
public void httpComponentsClientCreated() throws Exception {
ClientHttpRequestFactory factory = ClientHttpRequestFactoryFactory.HttpComponents.usingHttpComponents(
new ClientOptions(), new SslConfiguration());
ClientHttpRequestFactory factory =
ClientHttpRequestFactoryFactory.HttpComponents.usingHttpComponents(
new ClientOptions(), new SslConfiguration());
assertThat(factory, instanceOf(HttpComponentsClientHttpRequestFactory.class));
HttpClient httpClient = ((HttpComponentsClientHttpRequestFactory) factory).getHttpClient();
HttpClient httpClient = ((HttpComponentsClientHttpRequestFactory) factory)
.getHttpClient();
assertThat(httpClient, instanceOf(CloseableHttpClient.class));

View File

@@ -22,18 +22,15 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.AbstractUriTemplateHandler;
import java.net.URI;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertThat;
@RunWith(MockitoJUnitRunner.class)
public class CredHubClientUnitTests {
private static final String CREDHUB_URI = "https://credhub.cf.example.com:8844";
@@ -43,12 +40,14 @@ public class CredHubClientUnitTests {
@Test
public void restTemplateIsCreated() throws Exception {
RestTemplate restTemplate =
CredHubClient.createRestTemplate(CREDHUB_URI, clientHttpRequestFactory);
RestTemplate restTemplate = CredHubClient.createRestTemplate(CREDHUB_URI,
clientHttpRequestFactory);
assertThat(restTemplate.getUriTemplateHandler(), instanceOf(AbstractUriTemplateHandler.class));
assertThat(restTemplate.getUriTemplateHandler(),
instanceOf(AbstractUriTemplateHandler.class));
AbstractUriTemplateHandler uriTemplateHandler = (AbstractUriTemplateHandler) restTemplate.getUriTemplateHandler();
AbstractUriTemplateHandler uriTemplateHandler = (AbstractUriTemplateHandler) restTemplate
.getUriTemplateHandler();
assertThat(uriTemplateHandler.getBaseUrl(), equalTo(CREDHUB_URI));
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.springframework.credhub.support.CredentialDetails;
import org.springframework.credhub.support.WriteRequest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import java.util.Date;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import static org.springframework.credhub.core.CredHubTemplate.BASE_URL_PATH;
import static org.springframework.credhub.core.CredHubTemplate.ID_URL_PATH;
import static org.springframework.http.HttpMethod.PUT;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
@RunWith(Theories.class)
public class CredHubTemplateDetailResponseUnitTests extends CredHubTemplateUnitTestsBase {
private static final String CREDENTIAL_ID = "1111-1111-1111-1111";
private static final String CREDENTIAL_VALUE = "secret";
@DataPoint("responses")
public static ResponseEntity<CredentialDetails> successfulResponse =
new ResponseEntity<CredentialDetails>(CredentialDetails.detailsBuilder()
.name(NAME)
.id(CREDENTIAL_ID)
.passwordValue(CREDENTIAL_VALUE)
.versionCreatedAt(new Date())
.build(),
OK);
@DataPoint("responses")
public static ResponseEntity<CredentialDetails> httpErrorResponse =
new ResponseEntity<CredentialDetails>(CredentialDetails.detailsBuilder().build(),
UNAUTHORIZED);
@Theory
public void write(@FromDataPoints("responses") ResponseEntity<CredentialDetails> expectedResponse) {
WriteRequest request = WriteRequest.builder()
.name(NAME)
.passwordValue("secret")
.build();
when(restTemplate.exchange(BASE_URL_PATH, PUT,
new HttpEntity<WriteRequest>(request), CredentialDetails.class))
.thenReturn(expectedResponse);
if (!expectedResponse.getStatusCode().equals(HttpStatus.OK)) {
try {
credHubTemplate.write(request);
fail("Exception should have been thrown");
}
catch (CredHubException e) {
assertThat(e.getMessage(), containsString(expectedResponse.getStatusCode().toString()));
}
}
else {
CredentialDetails response = credHubTemplate.write(request);
assertResponseContainsExpectedCredentials(expectedResponse, response);
}
}
@Theory
public void getById(@FromDataPoints("responses") ResponseEntity<CredentialDetails> expectedResponse) {
when(restTemplate.getForEntity(ID_URL_PATH, CredentialDetails.class, CREDENTIAL_ID))
.thenReturn(expectedResponse);
if (!expectedResponse.getStatusCode().equals(HttpStatus.OK)) {
try {
credHubTemplate.getById(CREDENTIAL_ID);
fail("Exception should have been thrown");
}
catch (CredHubException e) {
assertThat(e.getMessage(), containsString(expectedResponse.getStatusCode().toString()));
}
}
else {
CredentialDetails response = credHubTemplate.getById(CREDENTIAL_ID);
assertResponseContainsExpectedCredentials(expectedResponse, response);
}
}
private void assertResponseContainsExpectedCredentials(
ResponseEntity<CredentialDetails> expectedResponse, CredentialDetails response) {
assertThat(response, notNullValue());
assertThat(response, equalTo(expectedResponse.getBody()));
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import java.util.List;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.springframework.credhub.support.CredentialDetails;
import org.springframework.credhub.support.CredentialDetailsData;
import org.springframework.http.ResponseEntity;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import static org.springframework.credhub.core.CredHubTemplate.NAME_URL_QUERY;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
@RunWith(Theories.class)
public class CredHubTemplateDetailsResponseUnitTests extends CredHubTemplateUnitTestsBase {
private static final String CREDENTIAL_ID = "1111-1111-1111-1111";
private static final String CREDENTIAL_VALUE = "secret";
@DataPoint("responses")
public static ResponseEntity<CredentialDetailsData> successfulResponse =
new ResponseEntity<CredentialDetailsData>(
CredentialDetailsData.builder()
.datum(CredentialDetails.detailsBuilder()
.name(NAME)
.id(CREDENTIAL_ID)
.passwordValue(CREDENTIAL_VALUE)
.build())
.build(),
OK);
@DataPoint("responses")
public static ResponseEntity<CredentialDetailsData> httpErrorResponse =
new ResponseEntity<CredentialDetailsData>(
CredentialDetailsData.builder()
.build(),
UNAUTHORIZED);
@Theory
public void getByNameWithString(@FromDataPoints("responses") ResponseEntity<CredentialDetailsData> expectedResponse) {
when(restTemplate.getForEntity(NAME_URL_QUERY, CredentialDetailsData.class, NAME.getName()))
.thenReturn(expectedResponse);
if (!expectedResponse.getStatusCode().equals(OK)) {
try {
credHubTemplate.getByName(NAME.getName());
fail("Exception should have been thrown");
}
catch (CredHubException e) {
assertThat(e.getMessage(), containsString(expectedResponse.getStatusCode().toString()));
}
}
else {
List<CredentialDetails> response = credHubTemplate.getByName(NAME.getName());
assertResponseContainsExpectedCredentials(expectedResponse, response);
}
}
@Theory
public void getByNameWithCredentialName(@FromDataPoints("responses") ResponseEntity<CredentialDetailsData> expectedResponse) {
when(restTemplate.getForEntity(NAME_URL_QUERY, CredentialDetailsData.class, NAME.getName()))
.thenReturn(expectedResponse);
if (!expectedResponse.getStatusCode().equals(OK)) {
try {
credHubTemplate.getByName(NAME);
fail("Exception should have been thrown");
}
catch (CredHubException e) {
assertThat(e.getMessage(), containsString(expectedResponse.getStatusCode().toString()));
}
}
else {
List<CredentialDetails> response = credHubTemplate.getByName(NAME);
assertResponseContainsExpectedCredentials(expectedResponse, response);
}
}
private void assertResponseContainsExpectedCredentials(
ResponseEntity<CredentialDetailsData> expectedResponse,
List<CredentialDetails> response) {
assertThat(response, notNullValue());
assertThat(response.size(), equalTo(expectedResponse.getBody().getData().size()));
assertThat(response.get(0), equalTo(expectedResponse.getBody().getData().get(0)));
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import java.util.Date;
import java.util.List;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.springframework.credhub.support.CredentialSummary;
import org.springframework.credhub.support.CredentialSummaryData;
import org.springframework.http.ResponseEntity;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import static org.springframework.credhub.core.CredHubTemplate.NAME_LIKE_URL_QUERY;
import static org.springframework.credhub.core.CredHubTemplate.PATH_URL_QUERY;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
@RunWith(Theories.class)
public class CredHubTemplateSummaryResponseUnitTests extends CredHubTemplateUnitTestsBase {
@DataPoint("responses")
public static ResponseEntity<CredentialSummaryData> successfulResponse =
new ResponseEntity<CredentialSummaryData>(
CredentialSummaryData.builder()
.credential(CredentialSummary.summaryBuilder()
.name(NAME)
.versionCreatedAt(new Date())
.build())
.build(),
OK);
@DataPoint("responses")
public static ResponseEntity<CredentialSummaryData> httpErrorResponse =
new ResponseEntity<CredentialSummaryData>(
CredentialSummaryData.builder()
.build(),
UNAUTHORIZED);
@Theory
public void findByNameWithString(@FromDataPoints("responses") ResponseEntity<CredentialSummaryData> expectedResponse) {
when(restTemplate.getForEntity(NAME_LIKE_URL_QUERY, CredentialSummaryData.class, NAME.getName()))
.thenReturn(expectedResponse);
if (!expectedResponse.getStatusCode().equals(OK)) {
try {
credHubTemplate.findByName(NAME.getName());
fail("Exception should have been thrown");
}
catch (CredHubException e) {
assertThat(e.getMessage(), containsString(expectedResponse.getStatusCode().toString()));
}
}
else {
List<CredentialSummary> response = credHubTemplate.findByName(NAME.getName());
assertResponseContainsExpectedCredentials(expectedResponse, response);
}
}
@Theory
public void findByNameWithCredentialName(@FromDataPoints("responses") ResponseEntity<CredentialSummaryData> expectedResponse) {
when(restTemplate.getForEntity(NAME_LIKE_URL_QUERY, CredentialSummaryData.class, NAME.getName()))
.thenReturn(expectedResponse);
if (!expectedResponse.getStatusCode().equals(OK)) {
try {
credHubTemplate.findByName(NAME);
fail("Exception should have been thrown");
}
catch (CredHubException e) {
assertThat(e.getMessage(), containsString(expectedResponse.getStatusCode().toString()));
}
}
else {
List<CredentialSummary> response = credHubTemplate.findByName(NAME);
assertResponseContainsExpectedCredentials(expectedResponse, response);
}
}
@Theory
public void findByPath(@FromDataPoints("responses") ResponseEntity<CredentialSummaryData> expectedResponse) {
when(restTemplate.getForEntity(PATH_URL_QUERY, CredentialSummaryData.class, NAME.getName()))
.thenReturn(expectedResponse);
if (!expectedResponse.getStatusCode().equals(OK)) {
try {
credHubTemplate.findByPath(NAME.getName());
fail("Exception should have been thrown");
}
catch (CredHubException e) {
assertThat(e.getMessage(), containsString(expectedResponse.getStatusCode().toString()));
}
}
else {
List<CredentialSummary> response = credHubTemplate.findByPath(NAME.getName());
assertResponseContainsExpectedCredentials(expectedResponse, response);
}
}
private void assertResponseContainsExpectedCredentials(
ResponseEntity<CredentialSummaryData> expectedResponse,
List<CredentialSummary> response) {
assertThat(response, notNullValue());
assertThat(response.size(),
equalTo(expectedResponse.getBody().getCredentials().size()));
assertThat(response.get(0),
equalTo(expectedResponse.getBody().getCredentials().get(0)));
}
}

View File

@@ -1,269 +0,0 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.credhub.support.CredentialDataResponse;
import org.springframework.credhub.support.CredentialData;
import org.springframework.credhub.support.FindResponse;
import org.springframework.credhub.support.SimpleCredentialName;
import org.springframework.credhub.support.WriteRequest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.credhub.core.CredHubTemplate.BASE_URL_PATH;
import static org.springframework.credhub.core.CredHubTemplate.NAME_LIKE_URL_QUERY;
import static org.springframework.credhub.core.CredHubTemplate.NAME_URL_QUERY;
import static org.springframework.credhub.core.CredHubTemplate.PATH_URL_QUERY;
import static org.springframework.credhub.core.CredHubTemplate.ID_URL_PATH;
import static org.springframework.http.HttpMethod.PUT;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
@RunWith(MockitoJUnitRunner.class)
public class CredHubTemplateTests {
private static final String CREDENTIAL_ID = "1111-1111-1111-1111";
private static final String CREDENTIAL_VALUE = "secret";
@Mock
private RestTemplate restTemplate;
private CredHubTemplate credHubTemplate;
private SimpleCredentialName name;
private CredentialDataResponse dataResponse;
private CredentialDataResponse dataResponseWithError;
private FindResponse findResponse;
private FindResponse findResponseWithError;
@Before
public void setUp() {
credHubTemplate = new CredHubTemplate(restTemplate);
name = SimpleCredentialName.builder().segments("example", "credential").build();
dataResponse = CredentialDataResponse.builder()
.datum(CredentialData.builder()
.name(name)
.id(CREDENTIAL_ID)
.passwordValue(CREDENTIAL_VALUE)
.build())
.build();
dataResponseWithError = CredentialDataResponse.builder()
.errorMessage("errorMessage message")
.build();
findResponse = FindResponse.builder()
.foundCredential(FindResponse.FoundCredential.builder()
.name(name)
.versionCreatedAt("")
.build())
.build();
findResponseWithError = FindResponse.builder()
.errorMessage("errorMessage message")
.build();
}
@Test
public void writeWithSuccess() {
WriteRequest request = WriteRequest.builder()
.name(name)
.passwordValue("secret")
.build();
when(restTemplate.exchange(BASE_URL_PATH, PUT, new HttpEntity<WriteRequest>(request), CredentialDataResponse.class))
.thenReturn(new ResponseEntity<CredentialDataResponse>(dataResponse, OK));
CredentialData response = credHubTemplate.write(request);
assertThat(response, notNullValue());
assertThat(response, equalTo(dataResponse.getData().get(0)));
}
@Test
public void writeWithErrorResponse() {
WriteRequest request = WriteRequest.builder()
.name(name)
.passwordValue("secret")
.build();
when(restTemplate.exchange(BASE_URL_PATH, PUT, new HttpEntity<WriteRequest>(request), CredentialDataResponse.class))
.thenReturn(new ResponseEntity<CredentialDataResponse>(dataResponseWithError, OK));
try {
credHubTemplate.write(request);
fail("Exception should have been thrown");
} catch (CredHubException e) {
assertThat(e.getMessage(), containsString(": errorMessage message"));
}
}
@Test
public void writeWithHttpError() {
WriteRequest request = WriteRequest.builder()
.name(name)
.passwordValue("secret")
.build();
when(restTemplate.exchange(BASE_URL_PATH, PUT, new HttpEntity<WriteRequest>(request), CredentialDataResponse.class))
.thenReturn(new ResponseEntity<CredentialDataResponse>(dataResponseWithError, HttpStatus.UNAUTHORIZED));
try {
credHubTemplate.write(request);
fail("Exception should have been thrown");
} catch (CredHubException e) {
assertThat(e.getMessage(), containsString(": " + HttpStatus.UNAUTHORIZED.toString()));
}
}
@Test
public void getByIdWithSuccess() {
when(restTemplate.getForEntity(ID_URL_PATH, CredentialDataResponse.class, CREDENTIAL_ID))
.thenReturn(new ResponseEntity<CredentialDataResponse>(dataResponse, OK));
CredentialData response = credHubTemplate.getById(CREDENTIAL_ID);
assertThat(response, notNullValue());
assertThat(response, equalTo(dataResponse.getData().get(0)));
}
@Test
public void getByIdWithError() {
when(restTemplate.getForEntity(ID_URL_PATH, CredentialDataResponse.class, CREDENTIAL_ID))
.thenReturn(new ResponseEntity<CredentialDataResponse>(dataResponseWithError, OK));
try {
credHubTemplate.getById(CREDENTIAL_ID);
fail("Exception should have been thrown");
} catch (CredHubException e) {
assertThat(e.getMessage(), containsString(": errorMessage message"));
}
}
@Test
public void getByIdWithHttpError() {
when(restTemplate.getForEntity(ID_URL_PATH, CredentialDataResponse.class, CREDENTIAL_ID))
.thenReturn(new ResponseEntity<CredentialDataResponse>(dataResponseWithError, UNAUTHORIZED));
try {
credHubTemplate.getById(CREDENTIAL_ID);
fail("Exception should have been thrown");
} catch (CredHubException e) {
assertThat(e.getMessage(), containsString(": " + HttpStatus.UNAUTHORIZED.toString()));
}
}
@Test
public void findByNameWithSuccess() {
when(restTemplate.getForEntity(NAME_LIKE_URL_QUERY, FindResponse.class, name.getName()))
.thenReturn(new ResponseEntity<FindResponse>(findResponse, OK));
FindResponse response = credHubTemplate.findByName(name.getName());
assertThat(response, notNullValue());
assertThat(response.getFoundCredentials().size(), equalTo(1));
assertThat(response.getFoundCredentials(), equalTo(findResponse.getFoundCredentials()));
}
@Test
public void findByNameWithError() {
when(restTemplate.getForEntity(NAME_LIKE_URL_QUERY, FindResponse.class, name.getName()))
.thenReturn(new ResponseEntity<FindResponse>(findResponseWithError, OK));
try {
credHubTemplate.findByName(name.getName());
fail("Exception should have been thrown");
} catch (CredHubException e) {
assertThat(e.getMessage(), containsString(": errorMessage message"));
}
}
@Test
public void findByNameWithHttpError() {
when(restTemplate.getForEntity(NAME_LIKE_URL_QUERY, FindResponse.class, name.getName()))
.thenReturn(new ResponseEntity<FindResponse>(findResponseWithError, UNAUTHORIZED));
try {
credHubTemplate.findByName(name.getName());
fail("Exception should have been thrown");
} catch (CredHubException e) {
assertThat(e.getMessage(), containsString(": " + HttpStatus.UNAUTHORIZED.toString()));
}
}
@Test
public void findByPathWithSuccess() {
when(restTemplate.getForEntity(PATH_URL_QUERY, FindResponse.class, name.getName()))
.thenReturn(new ResponseEntity<FindResponse>(findResponse, OK));
FindResponse response = credHubTemplate.findByPath(name.getName());
assertThat(response, notNullValue());
assertThat(response.getFoundCredentials().size(), equalTo(1));
assertThat(response.getFoundCredentials(), equalTo(findResponse.getFoundCredentials()));
}
@Test
public void findByPathWithError() {
when(restTemplate.getForEntity(PATH_URL_QUERY, FindResponse.class, name.getName()))
.thenReturn(new ResponseEntity<FindResponse>(findResponseWithError, OK));
try {
credHubTemplate.findByPath(name.getName());
fail("Exception should have been thrown");
} catch (CredHubException e) {
assertThat(e.getMessage(), containsString(": errorMessage message"));
}
}
@Test
public void findByPathWithHttpError() {
when(restTemplate.getForEntity(PATH_URL_QUERY, FindResponse.class, name.getName()))
.thenReturn(new ResponseEntity<FindResponse>(findResponseWithError, UNAUTHORIZED));
try {
credHubTemplate.findByPath(name.getName());
fail("Exception should have been thrown");
} catch (CredHubException e) {
assertThat(e.getMessage(), containsString(": " + HttpStatus.UNAUTHORIZED.toString()));
}
}
@Test
public void deleteByName() {
credHubTemplate.deleteByName(name.getName());
verify(restTemplate).delete(NAME_URL_QUERY, name.getName());
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.credhub.support.ServiceInstanceCredentialName;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.credhub.core.CredHubTemplate.INTERPOLATE_URL_PATH;
import static org.springframework.credhub.core.CredHubTemplate.NAME_URL_QUERY;
import static org.springframework.credhub.core.CredHubTemplate.VCAP_SERVICES_KEY;
import static org.springframework.http.HttpStatus.OK;
@RunWith(MockitoJUnitRunner.class)
public class CredHubTemplateUnitTests extends CredHubTemplateUnitTestsBase {
@Test
public void deleteByName() {
credHubTemplate.deleteByName(NAME.getName());
verify(restTemplate).delete(NAME_URL_QUERY, NAME.getName());
}
@Test
public void interpolateServiceData() throws IOException {
ServiceInstanceCredentialName credentialName = ServiceInstanceCredentialName.builder()
.serviceBrokerName("service-broker")
.serviceOfferingName("service-offering")
.serviceBindingId("1111-1111-1111-111")
.credentialName("credential_json")
.build();
Map<String, Object> request = buildVcap(credentialName.getName());
Map<String, Map<String, Object>> wrappedRequest = wrapVcap(request);
Map<String, Map<String, Object>> expectedResponse = new HashMap<String, Map<String, Object>>();
ParameterizedTypeReference<Map<String, Map<String, Object>>> type =
new ParameterizedTypeReference<Map<String, Map<String, Object>>>() {};
when(restTemplate.exchange(INTERPOLATE_URL_PATH, HttpMethod.POST,
new HttpEntity<Map<String, Map<String, Object>>>(wrappedRequest), type))
.thenReturn(new ResponseEntity<Map<String, Map<String, Object>>>(expectedResponse, OK));
Map<String, Object> response = credHubTemplate.interpolateServiceData(request);
assertThat(response, equalTo(expectedResponse.get(VCAP_SERVICES_KEY)));
}
private Map<String, Object> buildVcap(String credHubReferenceName) throws IOException {
String vcapServices = "{" +
" \"service-offering\": [" +
" {" +
" \"credentials\": {" +
" \"credhub-ref\": \"((" + credHubReferenceName + "))\"" +
" }," +
" \"label\": \"service-offering\"," +
" \"name\": \"service-instance\"," +
" \"plan\": \"standard\"," +
" \"tags\": [" +
" \"cloud-service\"" +
" ]," +
" \"volume_mounts\": []" +
" }" +
" ]" +
"}";
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(vcapServices, new TypeReference<Map<String, Object>>() {});
}
private Map<String, Map<String, Object>> wrapVcap(final Map<String, Object> serviceData) {
return new HashMap<String, Map<String, Object>>() {{
put(VCAP_SERVICES_KEY, serviceData);
}};
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import org.junit.Before;
import org.junit.Rule;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;
import org.springframework.credhub.support.SimpleCredentialName;
import org.springframework.web.client.RestTemplate;
public abstract class CredHubTemplateUnitTestsBase {
protected static final SimpleCredentialName NAME = new SimpleCredentialName("example", "credential");
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Mock
protected RestTemplate restTemplate;
protected CredHubTemplate credHubTemplate;
@Before
public void setUpCredHubTemplateUnitTests() {
credHubTemplate = new CredHubTemplate(restTemplate);
}
}

View File

@@ -18,19 +18,16 @@
package org.springframework.credhub.support;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
public class CredentialDataResponseUnitTests {
private ObjectMapper objectMapper = new ObjectMapper();
public class CredentialDetailsDataUnitTests extends JsonParsingUnitTestsBase {
@Test
public void deserializationWithPasswordValue() throws Exception {
@@ -38,7 +35,7 @@ public class CredentialDataResponseUnitTests {
" \"data\": [" +
" {" +
" \"type\": \"password\"," +
" \"version_created_at\": \"2017-04-14T19:37:28Z\"," +
" \"version_created_at\": \"" + testDateString + "\"," +
" \"id\": \"80cbb13f-7562-4e72-92de-f3ccf69eaa59\"," +
" \"name\": \"/c/service-broker-name/service-instance-name/binding-id/credentials-json\"," +
" \"value\": \"secret\"" +
@@ -46,21 +43,20 @@ public class CredentialDataResponseUnitTests {
" ]" +
"}";
CredentialDataResponse response = parseResponse(json);
CredentialDetailsData response = parseResponse(json);
assertThat(response.getData().size(), equalTo(1));
CredentialData data = response.getData().get(0);
CredentialDetails data = response.getData().get(0);
assertThat(data.getValueType(), equalTo(ValueType.PASSWORD));
assertThat(data.getVersionCreatedAt(), equalTo("2017-04-14T19:37:28Z"));
assertThat(data.getVersionCreatedAt(), equalTo(testDate));
assertThat(data.getId(), equalTo("80cbb13f-7562-4e72-92de-f3ccf69eaa59"));
assertThat(data.getName().getName(), equalTo("/c/service-broker-name/service-instance-name/binding-id/credentials-json"));
assertThat(data.getName().getName(), equalTo(
"/c/service-broker-name/service-instance-name/binding-id/credentials-json"));
assertThat(data.getValue(), instanceOf(String.class));
assertThat(data.getValue(), CoreMatchers.<Object>equalTo("secret"));
assertThat(response.getErrorMessage(), nullValue());
assertThat(data.getValue(), CoreMatchers.<Object> equalTo("secret"));
}
@Test
@@ -69,7 +65,7 @@ public class CredentialDataResponseUnitTests {
" \"data\": [" +
" {" +
" \"type\": \"json\"," +
" \"version_created_at\": \"2017-04-14T19:37:28Z\"," +
" \"version_created_at\": \"" + testDateString + "\"," +
" \"id\": \"80cbb13f-7562-4e72-92de-f3ccf69eaa59\"," +
" \"name\": \"/c/service-broker-name/service-instance-name/binding-id/credentials-json\"," +
" \"value\": {" +
@@ -81,40 +77,29 @@ public class CredentialDataResponseUnitTests {
" ]" +
"}";
CredentialDataResponse response = parseResponse(json);
CredentialDetailsData response = parseResponse(json);
assertThat(response.getData().size(), equalTo(1));
CredentialData data = response.getData().get(0);
CredentialDetails data = response.getData().get(0);
assertThat(data.getValueType(), equalTo(ValueType.JSON));
assertThat(data.getVersionCreatedAt(), equalTo("2017-04-14T19:37:28Z"));
assertThat(data.getVersionCreatedAt(), equalTo(testDate));
assertThat(data.getId(), equalTo("80cbb13f-7562-4e72-92de-f3ccf69eaa59"));
assertThat(data.getName().getName(), equalTo("/c/service-broker-name/service-instance-name/binding-id/credentials-json"));
assertThat(data.getName().getName(), equalTo(
"/c/service-broker-name/service-instance-name/binding-id/credentials-json"));
assertThat(data.getValue(), instanceOf(Map.class));
Map<String, Object> valueMap = (Map<String, Object>) data.getValue();
assertThat(valueMap.get("client_id"), CoreMatchers.<Object>equalTo("test-id"));
assertThat(valueMap.get("client_secret"), CoreMatchers.<Object>equalTo("test-secret"));
assertThat(valueMap.get("uri"), CoreMatchers.<Object>equalTo("https://example.com"));
assertThat(response.getErrorMessage(), nullValue());
assertThat(valueMap.get("client_id"), CoreMatchers.<Object> equalTo("test-id"));
assertThat(valueMap.get("client_secret"),
CoreMatchers.<Object> equalTo("test-secret"));
assertThat(valueMap.get("uri"),
CoreMatchers.<Object> equalTo("https://example.com"));
}
@Test
public void deserializationWithError() throws Exception {
String json = "{" +
" \"errorMessage\": \"some errorMessage text\"" +
"}";
CredentialDataResponse response = parseResponse(json);
assertThat(response.getErrorMessage(), equalTo("some errorMessage text"));
assertThat(response.getData(), nullValue());
}
private CredentialDataResponse parseResponse(String json) throws java.io.IOException {
return objectMapper.readValue(json, CredentialDataResponse.class);
private CredentialDetailsData parseResponse(String json)
throws java.io.IOException {
return objectMapper.readValue(json, CredentialDetailsData.class);
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import java.util.List;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
public class CredentialSummaryDataUnitTests extends JsonParsingUnitTestsBase {
@Test
public void deserializationWithCredentials() throws Exception {
String json = "{\n" +
" \"credentials\": [\n" +
" {\n" +
" \"name\": \"/c/deploy123/example1\",\n" +
" \"version_created_at\": \"" + testDateString + "\"\n" +
" },\n" +
" {\n" +
" \"name\": \"/c/deploy123/example2\",\n" +
" \"version_created_at\": \"" + testDateString + "\"\n" +
" },\n" +
" {\n" +
" \"name\": \"/c/deploy123/example3\",\n" +
" \"version_created_at\": \"" + testDateString + "\"\n" +
" }\n" +
" ]\n" +
"}";
CredentialSummaryData response = parseResponse(json);
assertThat(response.getCredentials().size(), equalTo(3));
List<CredentialSummary> credentials = response.getCredentials();
assertThat(credentials.get(0).getName().getName(),
equalTo("/c/deploy123/example1"));
assertThat(credentials.get(1).getName().getName(),
equalTo("/c/deploy123/example2"));
assertThat(credentials.get(2).getName().getName(),
equalTo("/c/deploy123/example3"));
for (CredentialSummary credential : credentials) {
assertThat(credential.getVersionCreatedAt(), equalTo(testDate));
}
}
@Test
public void deserializationWithEmptyCredentials() throws Exception {
String json = "{\n" +
" \"credentials\": [\n" +
" ]\n" +
"}";
CredentialSummaryData response = parseResponse(json);
assertThat(response.getCredentials(), notNullValue());
assertThat(response.getCredentials().size(), equalTo(0));
}
private CredentialSummaryData parseResponse(String json)
throws java.io.IOException {
return objectMapper.readValue(json, CredentialSummaryData.class);
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import java.text.DateFormat;
import java.util.Date;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import org.junit.Before;
public abstract class JsonParsingUnitTestsBase {
protected ObjectMapper objectMapper;
protected Date testDate;
protected String testDateString;
@Before
public void setUpJsonParsing() throws Exception {
DateFormat dateFormat = new ISO8601DateFormat();
objectMapper = new ObjectMapper();
objectMapper.setDateFormat(dateFormat);
testDateString = "2017-01-31T11:22:33Z";
testDate = dateFormat.parse(testDateString);
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
public class ServiceInstanceCredentialNameUnitTests {
@Test
public void simpleNameIsConstructed() {
CredentialName credentialName =
new ServiceInstanceCredentialName("broker-name", "service-name", "binding-id", "credential-name");
assertThat(credentialName.getName(), equalTo("/c/broker-name/service-name/binding-id/credential-name"));
}
}

View File

@@ -23,12 +23,19 @@ import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
public class CredHubRequestUnitTests {
public class SimpleCredentialNameUnitTests {
@Test
public void generateNameWithAllFields() {
CredHubRequest request = new CredHubRequest(new CredentialName("service-broker-name", "service-offering-name",
"service-binding-id", "credential-name"));
public void simpleNameIsConstructed() {
CredentialName credentialName =
new SimpleCredentialName("myorg", "example", "credential-name");
assertThat(request.getName(), equalTo("/c/service-broker-name/service-offering-name/service-binding-id/credential-name"));
assertThat(credentialName.getName(), equalTo("/c/myorg/example/credential-name"));
}
@Test
public void simpleNameIsParsed() {
CredentialName credentialName = new CredentialName("/c/myorg/example/credential-name");
assertThat(credentialName.getName(), equalTo("/c/myorg/example/credential-name"));
}
}

View File

@@ -18,20 +18,19 @@
package org.springframework.credhub.support;
import java.util.HashMap;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import java.util.HashMap;
import static org.springframework.credhub.support.AccessControlEntry.Operation.READ;
import static org.springframework.credhub.support.AccessControlEntry.Operation.WRITE;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.springframework.credhub.support.AccessControlEntry.Operation.READ;
import static org.springframework.credhub.support.AccessControlEntry.Operation.WRITE;
import static org.valid4j.matchers.jsonpath.JsonPathMatchers.hasJsonPath;
import static org.valid4j.matchers.jsonpath.JsonPathMatchers.hasNoJsonPath;
import static org.valid4j.matchers.jsonpath.JsonPathMatchers.isJson;
@@ -46,10 +45,8 @@ public class WriteRequestUnitTests {
public void setUp() {
mapper = new ObjectMapper();
requestBuilder = WriteRequest.builder()
.name(SimpleCredentialName.builder()
.segments("example", "credential")
.build());
requestBuilder = WriteRequest.builder().name(
new SimpleCredentialName("example", "credential"));
}
@Test
@@ -59,88 +56,80 @@ public class WriteRequestUnitTests {
@Test
public void serializationWithJsonValue() throws Exception {
requestBuilder
.jsonValue(new HashMap<String, Object>() {{
put("data", "value");
put("test", true);
}});
requestBuilder.jsonValue(new HashMap<String, Object>() {
{
put("data", "value");
put("test", true);
}
});
String jsonValue = serializeToJson(requestBuilder);
assertThat(jsonValue, allOf(
hasJsonPath("$.overwrite", equalTo(false)),
hasJsonPath("$.name", equalTo("/c/example/credential")),
hasJsonPath("$.type", equalTo("json")),
hasJsonPath("$.value.data", equalTo("value")),
hasJsonPath("$.value.test", equalTo(true))
));
assertThat(jsonValue,
allOf(hasJsonPath("$.overwrite", equalTo(false)),
hasJsonPath("$.name", equalTo("/c/example/credential")),
hasJsonPath("$.type", equalTo("json")),
hasJsonPath("$.value.data", equalTo("value")),
hasJsonPath("$.value.test", equalTo(true))));
assertThat(jsonValue, hasNoJsonPath("$.access_control_entries"));
}
@Test
public void serializationWithPasswordValue() throws Exception {
requestBuilder
.overwrite(true)
.passwordValue("secret");
requestBuilder.overwrite(true).passwordValue("secret");
String jsonValue = serializeToJson(requestBuilder);
assertThat(jsonValue, allOf(
hasJsonPath("$.overwrite", equalTo(true)),
hasJsonPath("$.name", equalTo("/c/example/credential")),
hasJsonPath("$.type", equalTo("password")),
hasJsonPath("$.value", equalTo("secret"))
));
assertThat(jsonValue,
allOf(hasJsonPath("$.overwrite", equalTo(true)),
hasJsonPath("$.name", equalTo("/c/example/credential")),
hasJsonPath("$.type", equalTo("password")),
hasJsonPath("$.value", equalTo("secret"))));
assertThat(jsonValue, hasNoJsonPath("$.access_control_entries"));
}
@Test
public void serializationWithOneAccessControl() throws Exception {
requestBuilder
.passwordValue("secret")
.accessControlEntry(AccessControlEntry.builder()
.app("app-id")
.operation(READ)
.build());
requestBuilder.passwordValue("secret").accessControlEntry(
AccessControlEntry.builder().app("app-id").operation(READ).build());
String jsonValue = serializeToJson(requestBuilder);
assertThat(jsonValue, allOf(
hasJsonPath("$.access_control_entries[0].actor", equalTo("mtls-app:app-id")),
hasJsonPath("$.access_control_entries[0].operations[0]", equalTo("read"))
));
assertThat(jsonValue,
allOf(hasJsonPath("$.access_control_entries[0].actor",
equalTo("mtls-app:app-id")),
hasJsonPath("$.access_control_entries[0].operations[0]",
equalTo("read"))));
}
@Test
public void serializationWithTwoAccessControls() throws Exception {
requestBuilder
.passwordValue("secret")
.accessControlEntry(AccessControlEntry.builder()
.app("app1-id")
.operation(READ)
.operation(WRITE)
.build())
.accessControlEntry(AccessControlEntry.builder()
.app("app2-id")
.operation(WRITE)
.operation(READ)
.build());
requestBuilder.passwordValue("secret")
.accessControlEntry(AccessControlEntry.builder().app("app1-id")
.operation(READ).operation(WRITE).build())
.accessControlEntry(AccessControlEntry.builder().app("app2-id")
.operation(WRITE).operation(READ).build());
String jsonValue = serializeToJson(requestBuilder);
assertThat(jsonValue, allOf(
hasJsonPath("$.access_control_entries[0].actor", equalTo("mtls-app:app1-id")),
hasJsonPath("$.access_control_entries[0].actor",
equalTo("mtls-app:app1-id")),
hasJsonPath("$.access_control_entries[0].operations[0]", equalTo("read")),
hasJsonPath("$.access_control_entries[0].operations[1]", equalTo("write")),
hasJsonPath("$.access_control_entries[1].actor", equalTo("mtls-app:app2-id")),
hasJsonPath("$.access_control_entries[1].operations[0]", equalTo("write")),
hasJsonPath("$.access_control_entries[1].operations[1]", equalTo("read"))
));
hasJsonPath("$.access_control_entries[0].operations[1]",
equalTo("write")),
hasJsonPath("$.access_control_entries[1].actor",
equalTo("mtls-app:app2-id")),
hasJsonPath("$.access_control_entries[1].operations[0]",
equalTo("write")),
hasJsonPath("$.access_control_entries[1].operations[1]",
equalTo("read"))));
}
private String serializeToJson(WriteRequest.WriteRequestBuilder requestBuilder) throws JsonProcessingException {
private String serializeToJson(WriteRequest.WriteRequestBuilder requestBuilder)
throws JsonProcessingException {
String jsonValue = mapper.writeValueAsString(requestBuilder.build());
assertThat(jsonValue, isJson());
return jsonValue;

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016-2017 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-credhub-demo</artifactId>
<name>Spring CredHub Demo</name>
<description>Spring CredHub Demo Application</description>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.6</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.credhub</groupId>
<artifactId>spring-credhub-core</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.credhub.configuration.CredHubConfiguration;
@Configuration
@Import(CredHubConfiguration.class)
public class CredHubDemoConfiguration {
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.demo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.credhub.core.CredHubTemplate;
import org.springframework.credhub.support.AccessControlEntry;
import org.springframework.credhub.support.CredentialDetails;
import org.springframework.credhub.support.CredentialName;
import org.springframework.credhub.support.CredentialSummary;
import org.springframework.credhub.support.SimpleCredentialName;
import org.springframework.credhub.support.WriteRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import static org.springframework.credhub.support.AccessControlEntry.Operation.READ;
@RestController
public class CredHubDemoController {
@Value("${vcap.application.application_id:}")
private String appId;
private CredHubTemplate credHubTemplate;
public CredHubDemoController(CredHubTemplate credHubTemplate) {
this.credHubTemplate = credHubTemplate;
}
@PostMapping("/test")
public Results runTests(@RequestBody Map<String, Object> value) {
Results results = new Results();
CredentialDetails credentialDetails = writeCredentials(value, results);
CredentialName credentialName = credentialDetails.getName();
getCredentialsById(credentialDetails.getId(), results);
getCredentialsByName(credentialName, results);
findCredentialsByName(credentialName, results);
findCredentialsByPath(credentialName.getName(), results);
interpolateServiceData(credentialName, results);
deleteCredentials(credentialName, results);
return results;
}
@SuppressWarnings("unchecked")
private <T> CredentialDetails writeCredentials(T value, Results results) {
try {
WriteRequest.WriteRequestBuilder requestBuilder = WriteRequest.builder()
.overwrite(true)
.name(new SimpleCredentialName("spring-credhub", "demo", "credentials_json"));
if (value instanceof String) {
requestBuilder.passwordValue((String) value);
}
else {
requestBuilder.jsonValue((Map<String, Object>) value);
}
if (StringUtils.hasText(appId)) {
requestBuilder.accessControlEntry(
AccessControlEntry.builder().app(appId).operation(READ).build());
}
WriteRequest request = requestBuilder.build();
CredentialDetails credentialDetails = credHubTemplate.write(request);
saveResults(results, "Successfully wrote credentials: ", credentialDetails);
return credentialDetails;
}
catch (Exception e) {
saveResults(results, "Error writing credentials: ", e.getMessage());
return null;
}
}
private void getCredentialsById(String id, Results results) {
try {
CredentialDetails retrievedDetails = credHubTemplate.getById(id);
saveResults(results, "Successfully retrieved credentials by ID: ", retrievedDetails);
} catch (Exception e) {
saveResults(results, "Error retrieving credentials by ID: ", e.getMessage());
}
}
private void getCredentialsByName(CredentialName name, Results results) {
try {
List<CredentialDetails> retrievedDetails = credHubTemplate.getByName(name);
saveResults(results, "Successfully retrieved credentials by name: ", retrievedDetails);
} catch (Exception e) {
saveResults(results, "Error retrieving credentials by name: ", e.getMessage());
}
}
private void findCredentialsByName(CredentialName name, Results results) {
try {
List<CredentialSummary> retrievedDetails = credHubTemplate.findByName(name);
saveResults(results, "Successfully found credentials by name: ", retrievedDetails);
} catch (Exception e) {
saveResults(results, "Error finding credentials by name: ", e.getMessage());
}
}
private void findCredentialsByPath(String path, Results results) {
try {
List<CredentialSummary> retrievedDetails = credHubTemplate.findByPath(path);
saveResults(results, "Successfully found credentials by path: ", retrievedDetails);
} catch (Exception e) {
saveResults(results, "Error finding credentials by path: ", e.getMessage());
}
}
private void interpolateServiceData(CredentialName name, Results results) {
try {
Map<String, Object> request = buildVcapServicesData(name.getName());
Map<String, Object> interpolatedServiceData = credHubTemplate.interpolateServiceData(request);
saveResults(results, "Successfully interpolated service data: ", interpolatedServiceData);
} catch (Exception e) {
saveResults(results, "Error interpolating service data: ", e.getMessage());
}
}
private void deleteCredentials(CredentialName name, Results results) {
try {
credHubTemplate.deleteByName(name);
saveResults(results, "Successfully deleted credentials");
} catch (Exception e) {
saveResults(results, "Error deleting credentials by name: ", e.getMessage());
}
}
private Map<String, Object> buildVcapServicesData(String credHubReferenceName) throws IOException {
String vcapServices = "{" +
" \"service-offering\": [" +
" {" +
" \"credentials\": {" +
" \"credhub-ref\": \"((" + credHubReferenceName + "))\"" +
" }," +
" \"label\": \"service-offering\"," +
" \"name\": \"service-instance\"," +
" \"plan\": \"standard\"," +
" \"tags\": [" +
" \"cloud-service\"" +
" ]," +
" \"volume_mounts\": []" +
" }" +
" ]" +
"}";
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(vcapServices, new TypeReference<Map<String, Object>>() {});
}
private void saveResults(Results results, String message) {
saveResults(results, message, null);
}
private void saveResults(Results results, String message, Object details) {
results.add(Collections.singletonMap(message, details));
}
private class Results extends ArrayList<Map<String, Object>> {
}
}